déclarant en avant une fonction qui utilise enable_if: appel ambigu
-
19-09-2019 - |
Question
J'ai du mal avant de déclarer une fonction qui utilise boost::enable_if
: le morceau de code suivant me donne une erreur de compilation:
// 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;
}
Lors de la compilation, je reçois une erreur « appel ambigu à foo ». Selon la définition de enable_if
, le « type » typedef correspond à void
quand la condition est vraie, donc autant que je peux voir, les deux signatures de match foo
. Pourquoi le compilateur pense qu'ils sont différents, et est-il une bonne façon de transmettre déclarer foo
(de préférence sans répéter la partie enable_if
)?
La solution
Ceci est non seulement un problème avec enable_if. Vous obtenez la même erreur sur Visual Studio et gcc avec le code suivant:
struct TypeVoid {
typedef void type;
};
template<typename T>
void f();
template<typename T>
typename T::type f() {
}
int main()
{
f<TypeVoid>();
return 0;
}
Je pense que le principal problème est que le type de retour (avant instanciation) fait partie de la signature d'une fonction de modèle. Il y a plus d'informations .
En ce qui concerne votre code, si la déclaration se réfère à la définition, vous devez correspondre à la fois:
// 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 déclaration fait référence à une autre fonction, le compilateur ne serait jamais en mesure de choisir le bon pour int , parce qu'ils sont tous deux valables. Cependant, vous pouvez désactiver la première pour int avec 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)
{
}
Autres conseils
Le problème est que la déclaration et la définition ne correspondent pas.
La solution est que la déclaration doit contenir exactement la même signature, et le bit 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;
}
Cette compile bien sur VC2008.