2013-06-13 2 views
4

Я пытаюсь обнаружить оператора плюс в классе со следующим кодом, который не работает с 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 ========== 
+1

Будь конкретнее - какие ошибки вы получаете, какой компилятор вы используете и что означает «компилятор умирает»? –

+0

Хорошо вставьте выходные данные –

+0

Не уверен, что это помогает. –

ответ

8

SFINAE означает "Ошибка замены не является ошибкой". Обратите внимание, что часть жирной - нет ничего, чтобы заменить в вашей клетчатой ​​функции

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, поэтому вам нужно указать их явно. Следовательно, вам нужно также сделать шаблон резервного копирования шаблоном.

+0

Совершенно верно, что мне не хватало функции, являющейся шаблоном, поэтому SFINAE никогда не применялся. Спасибо. –

+0

@BlairDavidson меня тоже, на самом деле, ха-ха. Редактирование. – jrok

+0

Привет, вы также помогли мне получить мою первую фиксацию для моего проекта liboperator на https://github.com/loosechainsaw/liboperator –

2

Проблема в том с «имеет оператор»:

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

Вы сообщаете компилятору, что есть всегда перегрузка has, которая принимает T1* и T2* и возвращает ... тип выражения T1 + T2. Но это выражение имеет тип, только если доступен оператор сложения.

Это заставляет вас в петлю: для того, чтобы определить, если operator+ существует (для заполнения value) компилятор должен определить тип возвращаемого operator+ ... который не может существовать!

+0

Спасибо, помощник. Будет ли игра –

+0

Любые мысли о том, как заставить ее работать? –

+0

@BlairDavidson: Чтобы быть откровенным, я не уверен, что это вообще возможно. – Jon

Смежные вопросы