Reenviar declarando una función que usa enable_if :llamada ambigua
-
19-09-2019 - |
Pregunta
Tengo algunos problemas para declarar una función que usa boost::enable_if
:el siguiente código me da un error de compilación:
// 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;
}
Al compilar, aparece un error de "llamada ambigua a foo".Según la definición de enable_if
, el typedef 'tipo' corresponde a void
cuando la condición es verdadera, por lo que puedo ver, las dos firmas de foo
fósforo.¿Por qué el compilador cree que son diferentes? ¿Existe una forma correcta de reenviar la declaración? foo
(preferiblemente sin repetir el enable_if
parte)?
Solución
Esto no es sólo un problema con enable_if. Se obtiene el mismo error en Visual Studio y gcc con el siguiente código:
struct TypeVoid {
typedef void type;
};
template<typename T>
void f();
template<typename T>
typename T::type f() {
}
int main()
{
f<TypeVoid>();
return 0;
}
Creo que el problema principal es que el tipo de retorno (antes de instancias) es parte de la firma de una función de plantilla. Hay más información aquí .
En cuanto a su código, si la declaración se refiere a la definición, debe coincidir tanto:
// 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)
{
}
Si la declaración se refiere a una función diferente, el compilador nunca sería capaz de elegir el correcto para int s, ya que ambos son válidos. Sin embargo, puede desactivar el primero para int s utilizando 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)
{
}
Otros consejos
El problema es que la declaración y la definición no coinciden.
La solución es que la declaración debe contener exactamente la misma firma, y el enable_if
poco.
#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;
}
Esto se compila bien en VC2008.