为什么类型约束 `std::convertible_to` 只能与一个模板参数一起使用?
Why can the type constraint `std::convertible_to` be used with only one template argument?
我已经滚动并搜索了 the standard and cppreference 数小时但无济于事,如果有人能为我解释这种情况,我将不胜感激:
我在看标准概念std::convertibe_to
。这是一个我理解的简单例子
class A {};
class B : public A {};
std::convertible_to<A, B>; // false
std::convertible_to<B, A>; // true
按预期工作。
现在还有另一种可能的使用方式,我不太明白
void foo(std::convertible_to<A> auto x) { /* ... */ }
,并且此函数可以轻松接受可转换为 A 的任何类型。但这很奇怪,因为第一个模板参数(“From”)基本上被删除,并在函数调用时推导。下面这个函数也可以工作,我相当确定它实际上等同于前一个
template<typename T, std::convertible_to<T> S>
void foo(S x) { /* ... */ }
当我们调用 foo
.
时,再次推导出 x
的类型
这有效,尽管模板需要两个参数。我也尝试使用 std::derived_from
并且它似乎有效。这种仅使用一个模板参数来指定概念的形式甚至出现在标准本身中,因此必须有一些语法来解释它。
请注意,存在的 std::convertible_to
中的 the only version 实际上是采用两个模板参数的。
谁能解释一下为什么会这样?
void foo( constraint<P0, P1, P2> auto x );
这大致翻译为
template<contraint<P0, P1, P2> X>
void foo( X x );
大致翻译为
template<class X> requires constraint<X, P0, P1, P2>
void foo( X x );
注意类型 X
如何 前置 到约束的模板参数。
所以在你的情况下,
template<typename T, std::convertible_to<T> S>
void foo(S x) { /* ... */ }
大致
template<typename T, class S>
requires std::convertible_to<S, T>
void foo(S x) { /* ... */ }
(我粗略地说,因为我相信它们在微妙的方面并不完全等同。例如,第二个引入了名称 X
,而第一个则没有。而且可能还有其他差异similar scale; 我的意思是理解翻译会让你理解翻译的内容。这不同于 for(:)
loop-for(;;)
loop correspondence; standard specified for(:)
loops in terms for(;;)
个循环,这不是我上面所说的。)
在模板参数列表中未提供模板概念的第一个参数的情况下,可以在多个位置使用 concept
名称。约束 auto
推导变量就是其中之一。
在这些情况下,第一个参数由某个表达式提供,通常使用模板参数推导规则。在约束函数参数的情况下,第一个参数由模板函数本身确定。也就是说,如果调用 foo(10)
,模板参数推导会将 auto
模板参数推导为 int
。因此,完整的概念将是 convertible_to<int, A>
.
我已经滚动并搜索了 the standard and cppreference 数小时但无济于事,如果有人能为我解释这种情况,我将不胜感激:
我在看标准概念std::convertibe_to
。这是一个我理解的简单例子
class A {};
class B : public A {};
std::convertible_to<A, B>; // false
std::convertible_to<B, A>; // true
按预期工作。
现在还有另一种可能的使用方式,我不太明白
void foo(std::convertible_to<A> auto x) { /* ... */ }
,并且此函数可以轻松接受可转换为 A 的任何类型。但这很奇怪,因为第一个模板参数(“From”)基本上被删除,并在函数调用时推导。下面这个函数也可以工作,我相当确定它实际上等同于前一个
template<typename T, std::convertible_to<T> S>
void foo(S x) { /* ... */ }
当我们调用 foo
.
x
的类型
这有效,尽管模板需要两个参数。我也尝试使用 std::derived_from
并且它似乎有效。这种仅使用一个模板参数来指定概念的形式甚至出现在标准本身中,因此必须有一些语法来解释它。
请注意,存在的 std::convertible_to
中的 the only version 实际上是采用两个模板参数的。
谁能解释一下为什么会这样?
void foo( constraint<P0, P1, P2> auto x );
这大致翻译为
template<contraint<P0, P1, P2> X>
void foo( X x );
大致翻译为
template<class X> requires constraint<X, P0, P1, P2>
void foo( X x );
注意类型 X
如何 前置 到约束的模板参数。
所以在你的情况下,
template<typename T, std::convertible_to<T> S>
void foo(S x) { /* ... */ }
大致
template<typename T, class S>
requires std::convertible_to<S, T>
void foo(S x) { /* ... */ }
(我粗略地说,因为我相信它们在微妙的方面并不完全等同。例如,第二个引入了名称 X
,而第一个则没有。而且可能还有其他差异similar scale; 我的意思是理解翻译会让你理解翻译的内容。这不同于 for(:)
loop-for(;;)
loop correspondence; standard specified for(:)
loops in terms for(;;)
个循环,这不是我上面所说的。)
在模板参数列表中未提供模板概念的第一个参数的情况下,可以在多个位置使用 concept
名称。约束 auto
推导变量就是其中之一。
在这些情况下,第一个参数由某个表达式提供,通常使用模板参数推导规则。在约束函数参数的情况下,第一个参数由模板函数本身确定。也就是说,如果调用 foo(10)
,模板参数推导会将 auto
模板参数推导为 int
。因此,完整的概念将是 convertible_to<int, A>
.