如果缺少operator+=
,我试图消除过载集的重载。
我知道如何检查T+T
是否合法:
template<typename T,
typename CheckTplusT = decltype(std::declval<T>() + std::declval<T>())>
void foo(T a, T b, ...)
{
a = a + b;
}
但这不适用于+=
template<typename T,
typename CheckTplusT = decltype(std::declval<T>() += std::declval<T>())>
void foo(T a, T b, ...)
{
a += b;
}
通过在decltype
中使用另一个表达式来修复此问题还是需要另一个SFINAE构造?
我需要从过载集中消除它的原因是它与另一个重载冲突,该重载接受一个functor用作+=
的替代。编译器是VS2013,gcc4.8
答案 0 :(得分:16)
我会把第二种形式写成:
template<typename T>
auto foo(T a, T b, ...) -> decltype( a+=b, void() )
{
a += b;
}
如果表达式decltype(a+=b, void())
有效,void
的推导类型将只是a+=b
,否则会导致SFINAE。
好吧,即使在第一种形式中,我也会使用尾随返回类型方法。
答案 1 :(得分:12)
lvalue
的左侧需要+=
,但您的解决方案有xvalue。正如dyp在评论中所述,您可以使用declval<T&>
来获得左值。这很好用(只是测试过):
template<typename T,
typename CheckTplusT = decltype(std::declval<T&>() += std::declval<T>())>
void foo(T a, T b, ...)
{
}
答案 2 :(得分:1)
添加此main()函数:
int main()
{
int x = 1, y = 2;
foo( x, y );
}
这就是编译器错误:
main.cpp: In function int main(): main.cpp:15:15: error: no matching
function for call to foo(int&, int&)
foo( x, y );
^ main.cpp:15:15: note: candidate is:
main.cpp:7:6: note: template<class T, class CheckTplusT> void foo(T, T, ...) void
foo(T a, T b, ...)
^ main.cpp:7:6: note: template argument deduction/substitution failed:
main.cpp:6:60: error:
using xvalue (rvalue reference) as lvalue
typename CheckTplusT = decltype(std::declval<T>() += std::declval<T>())>
关键字是using xvalue (rvalue reference) as lvalue
这是declval
的文档此解决方法适用于我:
template<typename T,
typename CheckTpluseqT = decltype(*std::declval<T*>() += *std::declval<T*>())>
void foo(T &a, T b, ...)
{
a += b;
}
int main()
{
int a = 1, b = 2;
foo( a, b );
std::cout << a << std::endl;
}
输出3
当然,您也可以使用declval<T&>
。
答案 3 :(得分:1)
这个怎么样?这是std::declval
之前使用的方法。
template<typename T,
typename CheckTplusT = decltype(*(T*)nullptr += std::declval<T>())>
void foo(T a, T b, ...)
{
a += b;
std::cout << "foo with +=" << std::endl;
}