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


У меня есть некоторые проблемы с объявлением функции, которая использует 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, тип typedef соответствует void, когда условие истинно, так что, насколько я могу видеть, две сигнатуры foo совпадают. Почему компилятор думает, что они разные, и есть ли правильный способ переадресации declare foo (предпочтительно без повторения части enable_if)?

2 4

2 ответа:

Это не только проблема с 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)       
{       
}

Если объявление ссылается на другую функцию, компилятор никогда не будет будьте в состоянии выбрать правильный для int s, потому что они оба действительны. Однако вы можете отключить первый для int s, используя disable_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.