我正在尝试用下面的代码检测一个类上的运算符plus,它不能与sfinae一起工作,任何专家都知道我遗漏了什么。
此外,当您删除要检测的类型上的运算符+时,编译器也会终止
template<class T1, class T2>
class has_addition_operator
{
private:
typedef char no;
static auto has(T1* a, T2* b) -> decltype( *a + *b);
static char has(...);
public:
enum{
value = (sizeof( has(new T1(), new T2())) != sizeof(no))
};
};
struct point{
int x, y;
point operator + (point const & o){
point r = *this;
r.x += o.x;
r.y += o.y;
return r;
}
};
bool has = liboperator::has_addition_operator<point,point>::value;
编译器具有以下输出:
1>------ Build started: Project: liboperator, Configuration: Debug Win32 ------
1> liboperator.cpp
1>c:\projects\liboperator\liboperator\liboperator\has_addition_operator.h(15): error C2784: 'std::_String_iterator<_Mystr> std::operator +(_String_iterator<_Mystr>::difference_type,std::_String_iterator<_Mystr>)' : could not deduce template argument for 'std::_String_iterator<_Mystr>' from 'point'
1> c:\program files (x86)\microsoft visual studio 11.0\vc\include\xstring(420) : see declaration of 'std::operator +'
1> c:\projects\liboperator\liboperator\liboperator\liboperator.cpp(26) : see reference to class template instantiation 'liboperator::has_addition_operator<T1,T2>' being compiled
1> with
1> [
1> T1=point,
1> T2=point
1> ]
1>c:\projects\liboperator\liboperator\liboperator\has_addition_operator.h(15): error C2784: 'std::_String_const_iterator<_Mystr> std::operator +(_String_const_iterator<_Mystr>::difference_type,std::_String_const_iterator<_Mystr>)' : could not deduce template argument for 'std::_String_const_iterator<_Mystr>' from 'point'
1> c:\program files (x86)\microsoft visual studio 11.0\vc\include\xstring(288) : see declaration of 'std::operator +'
1>c:\projects\liboperator\liboperator\liboperator\has_addition_operator.h(15): error C2784: 'std::move_iterator<_RanIt> std::operator +(_Diff,const std::move_iterator<_RanIt> &)' : could not deduce template argument for 'const std::move_iterator<_RanIt> &' from 'point'
1> c:\program files (x86)\microsoft visual studio 11.0\vc\include\xutility(1947) : see declaration of 'std::operator +'
1>c:\projects\liboperator\liboperator\liboperator\has_addition_operator.h(15): error C2784: 'std::_Array_iterator<_Ty,_Size> std::operator +(_Array_iterator<_Ty,_Size>::difference_type,std::_Array_iterator<_Ty,_Size>)' : could not deduce template argument for 'std::_Array_iterator<_Ty,_Size>' from 'point'
1> c:\program files (x86)\microsoft visual studio 11.0\vc\include\xutility(1801) : see declaration of 'std::operator +'
1>c:\projects\liboperator\liboperator\liboperator\has_addition_operator.h(15): error C2784: 'std::_Array_const_iterator<_Ty,_Size> std::operator +(_Array_const_iterator<_Ty,_Size>::difference_type,std::_Array_const_iterator<_Ty,_Size>)' : could not deduce template argument for 'std::_Array_const_iterator<_Ty,_Size>' from 'point'
1> c:\program files (x86)\microsoft visual studio 11.0\vc\include\xutility(1662) : see declaration of 'std::operator +'
1>c:\projects\liboperator\liboperator\liboperator\has_addition_operator.h(15): error C2784: 'std::reverse_iterator<_RanIt> std::operator +(_Diff,const std::reverse_iterator<_RanIt> &)' : could not deduce template argument for 'const std::reverse_iterator<_RanIt> &' from 'point'
1> c:\program files (x86)\microsoft visual studio 11.0\vc\include\xutility(1226) : see declaration of 'std::operator +'
1>c:\projects\liboperator\liboperator\liboperator\has_addition_operator.h(15): error C2784: 'std::_Revranit<_RanIt,_Base> std::operator +(_Diff,const std::_Revranit<_RanIt,_Base> &)' : could not deduce template argument for 'const std::_Revranit<_RanIt,_Base> &' from 'point'
1> c:\program files (x86)\microsoft visual studio 11.0\vc\include\xutility(1031) : see declaration of 'std::operator +'
1>c:\projects\liboperator\liboperator\liboperator\has_addition_operator.h(15): error C2676: binary '+' : 'point' does not define this operator or a conversion to a type acceptable to the predefined operator
========== Build: 0 succeeded, 1 failed, 0 up-to-date, 0 skipped ==========
发布于 2013-06-13 09:08:27
SFINAE是的缩写“替换失败 is not an error”。注意粗体部分-在您的checker函数中没有什么可替换的
static auto has(T1* a, T2* b) -> decltype( *a + *b);
因为它本身不是一个模板。当您实例化特征类时,它的签名是已知的,无论它是用什么类型实例化的,它都应该有operator+
。
您需要使has
本身成为一个模板。像这样的东西应该可以工作(未经测试):
template<typename U1, typename U2>
static constexpr auto has(int*)
-> decltype( std::declval<U1>() + std::declval<U2>(), yes() )
其中,yes
是与sizeof(no)
大小不同的类型的类型定义。按照上面的编写方式,编译器没有机会推导出U1
和U2
,所以您需要显式地指定它们。因此,您还需要将回退函数作为模板。
发布于 2013-06-13 08:55:18
问题出在"has operator“的情况下:
static auto has(T1* a, T2* b) -> decltype( *a + *b);
您告诉编译器,总是有一个has
重载,它接受一个T1*
和一个T2*
并返回...expression T1 + T2
的类型。但是这个表达式只有在加法运算符可用时才有类型。
这会使您陷入循环:为了确定operator+
是否存在(以填充value
),编译器必须确定operator+
的返回类型...这可能并不存在!
https://stackoverflow.com/questions/17082845
复制相似问题