C++ 概念与 std::is_convertible_to(缺失文档?)

huangapple go评论145阅读模式
英文:

C++ concept with std::is_convertible_to (missing doc?)

问题

我正在阅读 C++ 概念的文档(https://en.cppreference.com/w/cpp/language/constraints),并遇到了这个第一个示例:

template<typename T>
concept Hashable = requires(T a)
{
    { std::hash<T>{}(a) } -> std::convertible_to<std::size_t>;
};

完整示例在内置的 gcc C++20 中编译,文档中说:

std::hash<T>{}(a) 的表达式可以编译通过,
其结果可以转换为 std::size_t

我检查了 std::is_convertible_to 的签名,它有两个参数(https://en.cppreference.com/w/cpp/concepts/convertible_to):

template <class From, class To>

当只传递一个参数给概念模板时,为什么可以有两个参数?这是文档遗漏还是某种 C++20 概念魔法?

更新:概念规范内部假定有一个隐式参数(传递的类型)。

英文:

I am reading the docs for C++ concepts ( https://en.cppreference.com/w/cpp/language/constraints ) and stumbled upon this very first example:

template&lt;typename T&gt;
concept Hashable = requires(T a)
{
    { std::hash&lt;T&gt;{}(a) } -&gt; std::convertible_to&lt;std::size_t&gt;;
};

The full example compiles with built-in gcc C++20 and the docs say:

the expression std::hash&lt;T&gt;{}(a) compiles and
its result is convertible to std::size_t

I checked the signature of std::is_convertable_to and it has two parameters (https://en.cppreference.com/w/cpp/concepts/convertible_to):

template &lt;class From, class To&gt;

How can a concept-"template" have two parameters when only one argument is passed to it?
Is this omission on the docs side or is it some kind of C++20 concept-magic?

UPD: constraints inside concept specification assume one implicit argument (the passed type).

答案1

得分: 1

当您键入

template<std::convertible_to<std::size_t> X>
void foo(X x);

您只显式传递了一个模板参数。

发生的情况是编译器将其大致转换为

template<class X>
requires std::convertible_to<X, std::size_t>
void foo(X x);

将模板参数列表前置为类型 X 并检查概念。

同样的方式也适用于:

void foo(std::convertible_to<std::size_t> auto x);

其中 x 的类型通过前置到 std::convertible_to<std::size_t> 列表来测试,以及

template<typename T>
concept Hashable = requires(T a)
{
    { std::hash<T>{}(a) } -> std::convertible_to<std::size_t>;
};

{ std::hash<T>{}(a) } 的类型前置到 std::convertible_to<std::size_t> 中以查看它是否通过测试。

您可以在您的概念内添加额外的约束。请确保您的约束是不可分离的,因为最好这样做:

template<class T>
concept Bob = Alice<T> && Eve<T>;

如果 AliceEve 是可分离的概念,而不是将它们的所有要求合并成一个更大的 requires 块,语言将不会知道这一点。

如果可能的话,当您进行分离时,语言可以知道 BobAliceEve 中的任何一个都更受限制。如果您将所有 AliceEve 的要求合并到一个较大的 requires 块中,语言将无法知道这一点。

英文:

When you type

template&lt;std::convertible_to&lt;std::size_t&gt; X&gt;
void foo(X x);

you only pass one of the template parameters explicitly.

What happens is that the compiler converts this to (roughly)

template&lt;class X&gt;
requires std::convertible_to&lt;X, std::size_t&gt;
void foo(X x);

prepending the template argument lists with the type X and checking the concept.

The same works with:

void foo(std::convertible_to&lt;std::size_t&gt; auto x);

where the type of x is tested by prepending it to std::convertible_to&lt;std::size_t&gt; list, and the same with

template&lt;typename T&gt;
concept Hashable = requires(T a)
{
    { std::hash&lt;T&gt;{}(a) } -&gt; std::convertible_to&lt;std::size_t&gt;;
};

the type of { std::hash&lt;T&gt;{}(a) } is prepended into std::convertible_to&lt;std::size_t&gt; to see if it passes the test.

You can add extra constraints within your concept. Be sure to make sure your constraints non-separable, as it is better to do

template&lt;class T&gt;
concept Bob = Alice&lt;T&gt; &amp;&amp; Eve&lt;T&gt;;

if Alice and Eve are separable concepts, than to make Bob contain all of their requirements.

If you do this separation when possible, the language can know that Bob is more-constrained than either Alice or Eve. If, on the other hand, you combine all of Alice and Eves requirements into one larger requires block, the language won't know this.

huangapple
  • 本文由 发表于 2023年6月13日 17:12:00
  • 转载请务必保留本文链接:https://go.coder-hub.com/76463348.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定