Прямое объявление функции , которая использует enable_if :двусмысленный вызов
-
19-09-2019 - |
Вопрос
У меня возникли некоторые проблемы с прямым объявлением функции, которая использует 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.