2010-05-18 9 views
9

ich kann nicht herausfinden, warum dieses Segment ungelöst überladene Funktionsfehler gibt (gcc Version 4.3.4 (Debian 4.3.4-6)):C++ Boost-Funktion überladene Vorlage

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

können Sie mir helfen, danke

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 wird als

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

ich habe alle möglichen Vorlage explizite Instanziierung versucht, aber nothi ng scheint zu funktionieren. Das gleiche Problem scheint mit g ++ 4.1 aber nicht mit ICC

das funktioniert

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

und diese

#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

Funktioniert es ohne die 'static_cast' oder mit der generischen' function' Klasse? – GManNickG

+0

@GMan nein, funktioniert nicht ohne statische Besetzung (das war ein Zeichen der Verzweiflung). Was ist eine generische Funktionsklasse? – Anycorn

+0

Was Sie haben. Ich meine generisch nur als "nicht spezifisch für ein bestimmtes n". (Das heißt, "Funktion" ist allgemeiner als "Funktion2"). – GManNickG

Antwort

6

Update: dies ist ein Fehler, der gcc in gcc wurde behoben> = 4.4. bugzilla. Außerdem überarbeitete meine Antwort mit einem reduzierten Testfall.

Es gibt zwei Komponenten für dieses Problem: die Art und Weise boost :: Funktion nimmt einen Funktionszeiger und den gcc Fehler.

boost :: function - Es ist etwas seltsam über die Fehlermeldung Ihnen in der Frage aufgeführt sind; Es gibt keinen Kandidatenkonstruktor, der irgendetwas wie eine Funktionsadresse akzeptiert. Graben in die boost :: Funktion src, wird der entsprechende Konstruktor (Verlassen des enable_if Argument out):

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

So boost :: Funktion nicht, dass Sie überhaupt nicht helfen, in der Art eines Funktionszeiger angibt; Wenn die Funktion überladen ist, muss die Adresse umgewandelt werden, um ihren Typ anzugeben. Wenn eine überladene Funktionsadresse verwendet wird, kann die obige Vorlage nicht instanziiert werden und daher wird der entsprechende Konstruktor in der Fehlermeldung nicht angezeigt.

gcc Fehler - Wenn man sich die stl_algobase.h Header wieder anschauen, werden Sie sehen, gibt es zwei Vorlagen namens Max, ein zwei param-Version und eine ein param-Version. Dies sollte jedoch kein Problem mit Ihrem Code sein, oder? Der Begriff &max<int> sollte die einzelne Param-Version instanziieren und ihre Adresse annehmen. Das passiert jedoch nicht. Sie können das Problem in dem reduzierten (ohne Header) Testfall sehen:

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

Der obige Code führen zu einem unresolved overloaded function type mit gcc 4.3.4. Die Behebung ist, entweder die template <class T, class C> max(...){...} Definition zu entfernen oder eine static_cast<const int& (*)(const int&, const int&)>(...) um die Funktionsadresse hinzuzufügen. Ich vermute, dass das Problem mit der falschen Anwendung der teilweise expliziten Parameterspezifikation zu tun hat, die durch den Standard spezifiziert wird. Sie können nachfolgende Template-Parameter auslassen, um beispielsweise einen Rückgabewerttyp und nicht die Argumenttypen anzugeben. Das heißt, der Compiler instanziiert beide Vorlagen, wenn nur die vollständig angegebene Vorlage instanziiert werden soll. Es ist jedoch Spekulation, da der Fehler in gcc> = 4.4 behoben wurde.

Da man nicht auf stl_algobase.h; hacken sollte, schlägt die Arbeit um Vicente vor, ist die richtige, nämlich den Funktionszeiger auf den gewünschten Funktionszeiger Typ const int& (*)(const int&, const int&) zu werfen. In deinem Code funktioniert der Cast nicht, weil, wie GMan herausfindet, du auf eine boost :: function < ...> wirfst, die die Mehrdeutigkeit des Funktionszeigers nicht löst.

5

den Code zur Kritik, es gibt keinen Grund zu static_cast dass. Betrachten wir die ganze Guss tun wird ist der Konstruktor von boost::function2 verwenden, um einen neuen boost::function2 zu machen, dann wird es kopier konstruiert werden in m. Nur Konstrukt direkt in m:

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

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

Schließlich ist die bevorzugte Syntax von boost::function ist:

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

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

Die n-ary spezifischen Klassen sind für ältere Compiler-Unterstützung.

+0

dasselbe Problem, ich habe das schon mal probiert. Ich habe auch neuen Stil ausprobiert (zuerst). Ich postete Compiler Fehler – Anycorn

+0

@aaa: Ich verstehe. Ich werde nur dieses CW machen, um die Kritik zu verlassen. Vielleicht sollten Sie die eigentliche Fehlermeldung posten, ich sehe nichts falsch mit Ihrem Code. – GManNickG

3

Es scheint mit Versionen von gcc < 4.4

mit gcc-4.4.0 und msvc Express9 funktioniert es ein Problem mit der Definition des std :: max Template-Funktion zu sein.

Die folgenden Werke auch für gcc-3.4 und 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 
}