Прямое объявление функции , которая использует enable_if :двусмысленный вызов

StackOverflow https://stackoverflow.com/questions/2029278

Вопрос

У меня возникли некоторые проблемы с прямым объявлением функции, которая использует boost::enable_if:следующий фрагмент кода выдает мне ошибку компилятора:

// Declaration
template <typename T>
void foo(T t);

// Definition
template <typename T>
typename boost::enable_if<boost::is_same<T, int> >::type foo(T t)
{
}

int main()
{
    foo(12);
    return 0;
}

При компиляции я получаю ошибку "неоднозначный вызов foo".Согласно определению enable_if, значение 'type' typedef соответствует void когда условие истинно, так что, насколько я могу видеть, две сигнатуры foo совпадение.Почему компилятор считает, что они разные, и есть ли правильный способ переадресации объявления foo (предпочтительно без повторения enable_if часть)?

Это было полезно?

Решение

Это проблема не только с enable_if.Вы получаете ту же ошибку в Visual Studio и gcc со следующим кодом:

struct TypeVoid {
  typedef void type;
};

template<typename T>
void f();

template<typename T>
typename T::type f() {
}

int main()
{
  f<TypeVoid>();
  return 0;
}

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

Что касается вашего кода, если объявление ссылается на определение, вы должны соответствовать обоим:

// Declaration       
template <typename T>       
typename boost::enable_if<boost::is_same<T, int> >::type foo(T t);       

// Definition       
template <typename T>       
typename boost::enable_if<boost::is_same<T, int> >::type foo(T t)       
{       
}

Если объявление ссылается на другую функцию, компилятор никогда не сможет выбрать правильную для интs, потому что они оба действительны.Однако вы можете отключить первый из них для инты, использующие отключение_if:

// Other function declaration
template <typename T>
typename boost::disable_if<boost::is_same<T, int> >::type foo(T t);

// Defition
template <typename T>       
typename boost::enable_if<boost::is_same<T, int> >::type foo(T t)       
{       
}

Другие советы

Проблема в том, что объявление и определение не совпадают.

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

#include <boost/type_traits/is_same.hpp>
#include <boost/utility/enable_if.hpp>

// Declaration
template <typename T>
typename boost::enable_if<boost::is_same<T, int> >::type foo(T t);

// Definition
template <typename T>
typename boost::enable_if<boost::is_same<T, int> >::type foo(T t)
{
}

int main()
{
    foo(12);
    return 0;
}

Это отлично компилируется на VC2008.

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top