Operator Detection +

I am trying to detect a plus operator in a class with the following code that does not work with sfinae. Any expert has ideas about what I'm missing.

Also, the compiler dies when you delete the + operator by the type that you are trying to detect on

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; rx += ox; ry += oy; return r; } }; bool has = liboperator::has_addition_operator<point,point>::value; 

The compiler has the following output:

 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 ========== 
+4
source share
2 answers

SFINAE means "Replacement error is not an error." Pay attention to the highlighted part - there is nothing that could be replaced in your verification function

 static auto has(T1* a, T2* b) -> decltype( *a + *b); 

because this is not the template itself. When you create an instance of a feature class, its signature is already known and any type with which it was created must have operator+ .

You need to make has the template itself. Something like this should work (unverified):

 template<typename U1, typename U2> static constexpr auto has(int*) -> decltype( std::declval<U1>() + std::declval<U2>(), yes() ) 

Where yes is a typedef for a type with a different size than sizeof(no) . As written above, there is no way for the compiler to output U1 and U2 , so you need to explicitly specify them. Thus, you will also need to make the fallback function a template.

+8
source

The problem is in the case of "has an operator":

 static auto has(T1* a, T2* b) -> decltype( *a + *b); 

You tell the compiler that there is always an overload that takes T1* and a T2* and returns ... the expression type is T1 + T2 . But this expression is of type only if the addition operator is available.

This brings you into a loop: to determine the existence of operator+ (to fill in the value ), the compiler must determine the return type of operator+ ... which may not exist!

+2
source

Source: https://habr.com/ru/post/1485952/


All Articles