Шаблонные специализации неоднозначны - PullRequest
0 голосов
/ 18 июня 2011

Еще одна проблема с шаблоном!Я пытаюсь получить метод шаблона, который будет выводить объект, если у него есть перегрузка для оператора <<.У меня почти все работает, и я добавил enable_if для того, чтобы g ++ выбрал предполагаемую специализацию для каждого типа объектов. </p>

Дело в том, что с незагруженным объектом он работает вполне нормально.Но с перегрузкой обе мои специализации являются разумным выбором для g ++, и вместо компиляции он выдает неоднозначную ошибку перегрузки.

Вот код:

template<typename T>
  static void   Print(Stream& out, T& param, typename enable_if<CanPrint<T>::value>::type = 0)
  {
    out << param;
  }

  template<typename T>
  static void   Print(Stream& out, T& param)
  {
    out << "/!\\" << typeid(param).name() << " does not have any overload for <<.\n";
  }

Я понимаю, почемутакая вещь неоднозначна.Но я не могу придумать, как сделать это более очевидным ... как заставить компилятор понять, что вторая перегрузка должна выбираться только тогда, когда первая не может быть?

Ответы [ 3 ]

8 голосов
/ 18 июня 2011

Вы получите двусмысленность, потому что в обоих случаях у вас есть функция, которая принимает поток, за которым следует ваш тип T в качестве первых двух аргументов. Это работает, хотя:

#include <iostream>
#include <boost/utility/enable_if.hpp>
#include <typeinfo>

template <class T>
struct CanPrint { enum { value = 0 }; };

template <>
struct CanPrint<int> { enum { value = 1 }; };

template<typename T>
typename boost::enable_if<CanPrint<T>, void>::type 
    Print(std::ostream& out, T& param)
{
    out << param << std::endl;
}

template<typename T>
typename boost::disable_if<CanPrint<T>, void>::type 
    Print(std::ostream& out, T& param)
{
    out << "/!\\" << typeid(param).name() << " does not have any overload for <<.\n";
}

int main()
{
    int i = 1;
    double d = 2;

    Print(std::cout, i);
    Print(std::cout, d);
}
1 голос
/ 18 июня 2011

Я считаю, что это не имеет ничего общего с шаблонами.Свободная функция, перегруженная таким образом, выдает ту же самую неоднозначную ошибку.

проверьте этот простой пример кода. Это похоже на то, что вы делаете в своем примере шаблона:

void doSomething(int i, int j, int k );
void doSomething(int i, int j, int k = 10);


void doSomething(int i, int j, int k)
{

}

void doSomething(int i, int j)
{

}


int main()
{
    doSomething(10,20);
    return 0;
}

Ошибкаis:

prog.cpp:18: error: call of overloaded ‘doSomething(int, int)’ is ambiguous
prog.cpp:5: note: candidates are: void doSomething(int, int, int)
prog.cpp:10: note:                 void doSomething(int, int)

Очевидно, что вы не можете перегрузить функции таким способом только на основе аргументов по умолчанию.

1 голос
/ 18 июня 2011

Неоднозначность обусловлена ​​значением параметра по умолчанию.

Вызов Print(stream, whatever) может быть разрешен либо для первой версии с третьим параметром по умолчанию, либо для второй версии без третьего параметра.

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

...