是否应该考虑将转换运算符用于函数模板参数推导?
Should conversion operators be considered for function template argument deduction?
考虑以下 code:
template<typename>
struct S
{
operator S<int&>();
};
template<typename T>
void f(S<T&>);
int main()
{
f(S<int&&>{}); // gcc ok
// clang error
}
gcc 在临时参数上使用转换运算符,返回与 S<T&>
匹配的 S<int&>
,并接受调用。
clang 不考虑转换运算符,无法将 T&
与 int&&
匹配,并拒绝调用。
那么这里的语言是怎么说的呢?
GCC 在这里肯定是错误的:T&
和 T&&
是 [temp.deduct.type]/8 中的不同行,因此不兼容。为什么这样做尚不清楚。在另一个方向上犯错误会更有意义:如果参数被声明为 S<T&&>
并且参数是 S<int&>
类型,那么至少会有一个 T
(即, int&
) 这样(由于引用折叠)参数和参数类型相同。 (如果说涉及通用引用,也很容易犯错误。)
考虑以下 code:
template<typename>
struct S
{
operator S<int&>();
};
template<typename T>
void f(S<T&>);
int main()
{
f(S<int&&>{}); // gcc ok
// clang error
}
gcc 在临时参数上使用转换运算符,返回与 S<T&>
匹配的 S<int&>
,并接受调用。
clang 不考虑转换运算符,无法将 T&
与 int&&
匹配,并拒绝调用。
那么这里的语言是怎么说的呢?
GCC 在这里肯定是错误的:T&
和 T&&
是 [temp.deduct.type]/8 中的不同行,因此不兼容。为什么这样做尚不清楚。在另一个方向上犯错误会更有意义:如果参数被声明为 S<T&&>
并且参数是 S<int&>
类型,那么至少会有一个 T
(即, int&
) 这样(由于引用折叠)参数和参数类型相同。 (如果说涉及通用引用,也很容易犯错误。)