2010-05-18 3 views
9

surchargé fonction boost je ne peux pas comprendre pourquoi ce segment donne non résolue erreur de fonction surchargée (version gcc 4.3.4 (Debian 4.3.4-6)):C++ modèle

#include <algorithm> 
#include <boost/function.hpp> 

// this does not work 
int main1() 
{ 
    typedef boost::function<const int&(const int&, const int&)> max; 
    max m(&std::max<int>); 
} 

// this does not work 
int main2() { 
    typedef boost::function2<const int&, const int&, const int&> max; 
    max m(static_cast<max>(&std::max<int>)); 
} 

pouvez-vous me aider, merci

test.cpp: In function âint main()â: 
test.cpp:7: error: no matching function for call to âboost::function2<const int&, const int&, const int&>::function2(<unresolved overloaded function type>)â 
/usr/include/boost/function/function_template.hpp:747: note: candidates are: boost::function2<R, T1, T2>::function2(const boost::function2<R, T1, T2>&) [with R = const int&, T0 = const int&\ 
, T1 = const int&] 
/usr/include/boost/function/function_template.hpp:739: note:     boost::function2<R, T1, T2>::function2(boost::function2<R, T1, T2>::clear_type*) [with R = const int&, T0 = cons\ 
t int&, T1 = const int&] 
/usr/include/boost/function/function_template.hpp:707: note:     boost::function2<R, T1, T2>::function2() [with R = const int&, T0 = const int&, T1 = const int&] 

max/min est définie comme

template<typename _Tp> 
    inline const _Tp& 
    max(const _Tp& __a, const _Tp& __b) 
    { 
     // concept requirements 
     __glibcxx_function_requires(_LessThanComparableConcept<_Tp>) 
     //return __a < __b ? __b : __a; 
     if (__a < __b) 
     return __b; 
     return __a; 
    } 

J'ai essayé toutes sortes de modèle instanciation explicite, mais nothi ng semble fonctionner. Même problème apparaît avec g ++ 4.1 mais pas avec la CPI

cela fonctionne

#include <algorithm> 
#include <boost/function.hpp> 

namespace std_ { 
    template<typename _Tp> 
    inline const _Tp& 
    max(const _Tp& __a, const _Tp& __b) 
    { 
     // concept requirements 
     //return __a < __b ? __b : __a; 
     if (__a < __b) 
      return __b; 
     return __a; 
    } 
} 

int main() 
{ 
    typedef const int &T; 
    typedef boost::function<T(T,T)> min_; 
    //typedef const int&(*min_)(const int&, const int&); 
    min_ m(::std_::max<int>); 
} 

et ce

#include <algorithm> 
#include <boost/function.hpp> 

int main() 
{ 
    //typedef const int &T; 
    //typedef boost::function<T(T,T)> min_; 
    typedef const int&(*min_)(const int&, const int&); 
    min_ m(::std::max<int>); 
} 
+0

Fonctionne-t-il sans static_cast ou avec la classe générique 'function'? – GManNickG

+0

@GMan non, ne fonctionne pas sans statique (c'était un signe de désespoir). Qu'est-ce que la classe de fonction générique? – Anycorn

+0

Ce que vous avez. Je veux dire générique tout comme "non spécifique à un n spécifique". (C'est-à-dire que "function" est plus générique que "function2"). – GManNickG

Répondre

6

Mise à jour: c'est un bug gcc qui a été corrigé dans gcc> = 4.4. bugzilla. Aussi, révisé ma réponse avec un cas de test réduit.

Il y a deux composants à ce problème: la façon dont boost :: function adopte un pointeur de fonction et le bogue gcc.

boost :: fonction - Il y a quelque chose d'étrange au sujet du message d'erreur que vous avez énumérés dans la question; aucun constructeur candidat n'accepte quoi que ce soit comme une adresse de fonction. Creuser dans la fonction boost :: src, le constructeur concerné est (en laissant de côté l'argument enable_if):

template<typename Functor> 
function(Functor f) : base_type(f) {} 

coup de pouce pour fonction :: ne vous aide pas du tout en spécifiant le type d'un pointeur de fonction; si la fonction est surchargée, l'adresse doit être castée pour spécifier son type. Si une adresse de fonction surchargée est utilisée, le modèle ci-dessus ne peut pas être instancié et, par conséquent, le constructeur approprié n'apparaît pas dans le message d'erreur.

bug gcc - Si vous regardez l'en-tête de stl_algobase.h à nouveau, vous verrez qu'il ya deux modèles nommés max, une version deux et une param version param. Cela ne devrait pas poser de problème avec votre code, n'est-ce pas? Le terme &max<int> devrait instancier la seule version de param et prendre son adresse. Cependant, ce n'est pas ce qui arrive. Vous pouvez voir le problème dans la réduction (sans en-tête) cas de test:

template <class T> 
const T& max(const T& x, const T& y){ 
    return x > y ? x : y; 
} 

template <class T, class C> 
const T& max(const T& x, const T& y, C comp){ 
    return comp(x, y) ? y : x; 

} 

template <class R, class A0, class A1> 
struct functor{ 
    template <class F> 
    functor(F f) : f(f) {} 
    R (*f)(A0, A1); 
}; 

int main(void){ 
    functor<const int&, const int&, const int&> func(&max<int>); 
    return 0; 
} 

Les résultats de code ci-dessus dans un unresolved overloaded function type avec gcc 4.3.4. La solution consiste à supprimer la définition template <class T, class C> max(...){...} ou à ajouter un static_cast<const int& (*)(const int&, const int&)>(...) autour de l'adresse de la fonction. Je suppose que le problème a à voir avec l'application incorrecte de la spécification de paramètre explicite partielle, qui est spécifiée par la norme. Il vous permet de laisser de côté les paramètres du modèle final pour faire des choses comme spécifier un type de valeur de retour et pas les types d'arguments. C'est-à-dire que le compilateur instancie le modèle à la fois lorsqu'il devrait seulement instancier le modèle entièrement spécifié. Sa spéculation théorique, puisque le bug a été corrigé dans gcc> = 4.4.

Comme il ne faut pas pirater à stl_algobase.h;), le travail autour de Vicente suggère est la bonne, à savoir transtyper le pointeur de fonction du type de pointeur de fonction souhaitée const int& (*)(const int&, const int&). Dans votre code, la distribution ne fonctionne pas car, comme le fait remarquer GMan, vous utilisez une fonction boost :: function < ...>, qui ne fait rien pour résoudre l'ambiguïté du pointeur de fonction.

5

Pour critiquer le code, il n'y a aucune raison de static_cast que. Considérer tout le casting va faire est d'utiliser le constructeur de boost::function2 pour faire un nouveau boost::function2, alors il sera construit en copie dans m. Il suffit de construire directement dans m:

#include <algorithm> 
#include <boost/function.hpp> 

int main() 
{ 
    typedef boost::function2<const int&, const int&, const int&> max; 
    max m(&std::max<int>); 
} 

Enfin, la syntaxe préférée de boost::function est:

#include <algorithm> 
#include <boost/function.hpp> 

int main() 
{ 
    typedef boost::function<const int&(const int&, const int&)> max; 
    max m(&std::max<int>); 
} 

Les classes spécifiques n-aire sont pour le soutien du compilateur plus.

+0

même problème, j'ai déjà essayé. J'ai essayé le nouveau style aussi (premier). J'ai posté une erreur de compilation – Anycorn

+0

@aaa: Je vois. Je vais juste faire ce CW puis quitter la critique. Peut-être que vous devriez publier le message d'erreur réel, je ne vois rien de mal avec votre code. – GManNickG

3

Il semble y avoir un problème avec la définition de la std :: fonction de modèle max avec les versions de gcc 4.4 <

Avec gcc-4.4.0 et msvc Express9 cela fonctionne.

Les travaux suivants pour gcc-3.4 et gcc-4,3

int main1() 
{ 
    int res = std::max(1,2); 
    typedef boost::function<const int&(const int&, const int&)> max; 
    max m(static_cast<const int&(*)(const int&, const int&)>(std::max<int>)); 

    return 0 
}