为什么类型约束 `std::convertible_to` 只能与一个模板参数一起使用?

我已经滚动并搜索了标准和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) { /* ... */ }

x当我们调用 时,再次推导出的类型foo

尽管模板需要两个参数,但这仍然有效。我也尝试过std::derived_from,它似乎有效。这种仅用一个模板参数指定概念的形式甚至出现在标准本身中,因此必须有一些语法来解释它。

请注意,只有版本的std::convertible_to存在,其实是一个有两个模板参数。

任何人都可以澄清为什么这有效?

回答

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,而第一个没有。并且可能还有其他类似规模的差异;我的意思是理解翻译会给你什么是翻译的理解这不像。for(:)环-for(;;)环对应;该标准规定for(:)的循环来讲for(;;)循环,这是不是我自称以上)。


有几个位置concept可以使用名称,其中模板概念的第一个参数未在模板参数列表中提供。约束auto推导变量就是其中之一。

在这些情况下,第一个参数由某个表达式提供,通常使用模板参数推导规则。在约束函数参数的情况下,第一个参数由模板函数本身决定。也就是说,如果您调用foo(10),模板参数推导会将auto模板参数推导为int. 因此,完整的概念将是convertible_to<int, A>


以上是为什么类型约束 `std::convertible_to` 只能与一个模板参数一起使用?的全部内容。
THE END
分享
二维码
< <上一篇
下一篇>>