2010-01-08 6 views
4

j'ai une certaine difficulté à déclarer en avant une fonction qui utilise boost::enable_if: la pièce de code suivante me donne une erreur de compilation:déclarant avant une fonction qui utilise enable_if: appel ambigu

// 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 un " appel ambigu à foo "erreur. Selon la définition de enable_if, le type 'typedef' correspond à void lorsque la condition est vraie, donc autant que je peux voir, les deux signatures de foo correspondent. Pourquoi le compilateur pense-t-il qu'ils sont différents, et existe-t-il un moyen correct d'envoyer la déclaration foo (de préférence sans répéter la partie enable_if)?

+0

Le match est le problème, le compilateur ne peut pas décider que vous souhaitez utiliser modèle que. –

Répondre

3

Ce n'est pas 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 here.

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 s, car ils sont tous les deux valides. Cependant, vous pouvez désactiver la première pour int s en utilisant 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)  
{  
} 
1

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; 
} 

Cela compile une amende sur VC2008.

Questions connexes