Специализация шаблонов неоднозначна

80
8

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


Вещь, с перегруженным объектом non-, работает очень хорошо. Но с перегруженным, обе моей специализации являются разумным выбором для 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";
}


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

спросил(а) 2011-06-18T12:03:00+04:00 8 лет, 9 месяцев назад
1
Решение
106

Вы получите двусмысленность, потому что в обоих случаях у вас есть функция, которая берет поток, за которым следует ваш тип 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);
}

ответил(а) 2011-06-18T12:15:00+04:00 8 лет, 9 месяцев назад
50

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


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


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;
}

Ошибка:


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)

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

ответил(а) 2011-06-18T12:07:00+04:00 8 лет, 9 месяцев назад
52

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


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


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

ответил(а) 2011-06-18T12:06:00+04:00 8 лет, 9 месяцев назад
Ваш ответ
Введите минимум 50 символов
Чтобы , пожалуйста,
Выберите тему жалобы:

Другая проблема