2014-11-14 8 views
3

по какой-то причине у меня есть два класса, реализующих оператор «+» с шаблонами, (Я делаю это, потому что хочу, чтобы все дети этих двух классов могли его использовать).C++ template, неоднозначная перегрузка

Я дошедший до очень простого кода, реализующего то, что я хотел бы использовать:

#include <type_traits> 

class A{}; 

template<typename T> 
A operator+(T& lhs,int rhs){ 
    static_assert(std::is_base_of<A, T>::value, "T must inherit from A"); 
    A to_return; 
    return to_return; 
} 

class B{}; 

template<typename T> 
B operator+(T& lhs,int rhs){ 
    static_assert(std::is_base_of<B, T>::value, "T must inherit from B"); 
    B to_return; 
    return to_return; 
} 


int main() 
{ 
    A u; 
    A v = u+1; 
} 

При компиляции, компилятор (г ++ или Intel) возвращаю следующее сообщение об ошибке:

  • g ++: main.cpp: 25: 11: ошибка: неоднозначная перегрузка для «operator +» в «u + 1» main.cpp: 25: 11: примечание: кандидаты: main.cpp: 6: 3: note: A оператор + (T &, int) [с T = A] main.cpp: 15: 3: примечание: оператор B + (T &, int) [с T = A]

  • icpc: main.cpp (25): ошибка: более чем один оператор «+» соответствует этим операндам : шаблона функция "оператор + (Т &, целые)" шаблона функции "оператор в + (Т &, целый)" типов операндов: А + INT А против = и + 1; ^

Хотя это не так неоднозначно, как v должно быть типа А, таким образом, только первый шаблон должен работать.

Любая идея обойти это, поддерживая два оператора шаблонов?

Или еще одна идея иметь оператора, работающего для всех детей A и B? I.e. для всех классов С ребенком А, я хотел бы, чтобы иметь возможность написать A w = u + 1; //where u is of type C. И то же самое для B.

Спасибо,

Tony

EDIT:

После ответа данного by Barry, std :: enable_if выполняет задание. Тем не менее, оказывается, что то, что мне нужно было именно в том, чтобы использовать два typenames, метод, предложенный Барри должен быть немного изменен, чтобы добавить эту возможность:

#include <type_traits> 
#include <iostream> 

class A{}; 

template<typename T1,typename T2 = typename std::enable_if<std::is_base_of<A,T1>::value, A>::type> 
A operator+(T1& lhs,T2& rhs){ 
    A to_return; 
    return to_return; 
} 

class B{}; 

template<typename T1,typename T2 = typename std::enable_if<std::is_base_of<B,T1>::value, B>::type> 
B operator+(T2& lhs,T2& rhs){ 
    B to_return; 
    return to_return; 
} 


int main() 
{ 
    A u; 
    A w = u+u; 
} 

Затем он работает отлично, даже если T1 и T2 разные дети A.

+0

Просто не строят операторы шаблона принимая ничего (я считаю это недостатком конструкции) - быть более конкретным –

+2

* "Хотя это не так двусмысленно, поскольку v должно быть типа A, поэтому должен работать только первый шаблон ». * Откуда вы взяли эту идею? – jrok

+0

T может быть любым дочерним элементом A (соответственно B) для первого (соответственно второго). Если есть какой-то способ сообщить об этом компилятору, я в порядке с этим решением. – Tony

ответ

8

Разрешение перегрузки основано исключительно на функции подписи, которая является ее именем, ее квалификацией cv и ее параметрами.

Для вашего первого, то есть:

operator+(T& lhs, int rhs); 

А для второго, что также:

operator+(T& lhs, int rhs); 

С тех идентичны, компилятор не может различать два - следовательно, двусмысленность.Один из способов обойти это, чтобы переместить в статические проверки возвращаемого типа и использовать SFINAE:

template<typename T> 
typename std::enable_if< 
    std::is_base_of<A, T>::value, 
    A 
>::type 
operator+(T& lhs,int rhs){ 
    // stuff 
} 

И то же самое для другого оператора. Это будет работать до тех пор, пока вы не попробуете его с T, который исходит из обоих, и затем он снова станет неоднозначным.

Или, в зависимости от того, что вы на самом деле делать с lhs, просто:

A operator+(A& lhs, int rhs); // already accepts anything that derives from A 
+0

Вот [рабочий образец] (http://ideone.com/rLEi6y), который меняет код в соответствии с рекомендациями. –

+0

Спасибо, именно то, что я искал. И действительно, «оператор + (A & lhs, int rhs)»; делает работу! – Tony

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