使用 SFINAE 将结构的转发引用作为函数模板中的参数
Forwarding reference for struct as a parameter in a function template with SFINAE
我想知道为什么这段代码无法编译:
struct S{ int m; };
template<class T, class = std::enable_if_t<std::is_same_v<T, S>>>
T& operator+=(T&& arg0, int arg1)
{
arg0.m += arg1;
return arg0;
}
int main()
{
S val0{ 0 }; int val1{ 1 };
val0 += val1;
return 0;
}
但是当删除 SFINAE 或使用基本整数而不是结构(通过适当的模板代码更改)时,它确实可以编译。
这里的问题是对于转发引用,由于 val0
是一个左值,T
被推断为 S&
,而不是 S
。这导致 std::is_same_v<T, S>
失败,因为 S
与 S&
不同。要解决此问题,您可以使用 std::decay_t
删除引用,例如
template<class T, std::enable_if_t<std::is_same_v<std::decay_t<T>, S>, int> = 0>
T& operator+=(T&& arg0, int arg1)
{
arg0.m += arg1;
return arg0;
}
我还调整了模板以使用默认的非类型参数而不是默认的类型参数。这样做可以让您更轻松地重载函数,因为与默认值不同,默认类型参数不是函数签名的一部分。
我想知道为什么这段代码无法编译:
struct S{ int m; };
template<class T, class = std::enable_if_t<std::is_same_v<T, S>>>
T& operator+=(T&& arg0, int arg1)
{
arg0.m += arg1;
return arg0;
}
int main()
{
S val0{ 0 }; int val1{ 1 };
val0 += val1;
return 0;
}
但是当删除 SFINAE 或使用基本整数而不是结构(通过适当的模板代码更改)时,它确实可以编译。
这里的问题是对于转发引用,由于 val0
是一个左值,T
被推断为 S&
,而不是 S
。这导致 std::is_same_v<T, S>
失败,因为 S
与 S&
不同。要解决此问题,您可以使用 std::decay_t
删除引用,例如
template<class T, std::enable_if_t<std::is_same_v<std::decay_t<T>, S>, int> = 0>
T& operator+=(T&& arg0, int arg1)
{
arg0.m += arg1;
return arg0;
}
我还调整了模板以使用默认的非类型参数而不是默认的类型参数。这样做可以让您更轻松地重载函数,因为与默认值不同,默认类型参数不是函数签名的一部分。