2012-04-11 11 views
0

Der folgende Code geben Fehler durch Leitung verursacht kompilieren 17:Doppel boost :: bind Ursache Fehler bei der Kompilierung

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

void func() 
{} 

class A{ 
public: 

    template <typename T> 
    static void foo(T const& arg){} 

    template <typename T> 
    void bar(T const& arg){ 
     boost::bind(&A::foo<T>, arg); //OK 
     boost::function<T> functor1 = boost::bind(func); //OK 
     boost::function<T> functor2 = boost::bind(&A::foo<T>, arg); //ERROR, LINE 17 
    } 
}; 

int main() 
{ 
    A obj1; 
    obj1.bar(func); 
} 

Die Frage ist, was die protoype von functor2 in Zeile sollte 17 sein?
Wenn ich die functor2 Prototyp zu sein „boost :: Funktion < void() > wirklich behalten wollen, wie die Boost machen :: bind zurückzukehren, eine solche Art

Der Übersetzungsfehler ist: usr/include/boost/bind/bind.hpp:253: error: invalid initialization of reference of type 'void (&)()' from expression of type 'void (*)()'
Was ist das?

+0

Try boost :: function functor2 = boost :: bind (& A :: foo , arg); – Lou

+0

Das funktioniert nicht. weil T bereits "void (*)()" ist. –

Antwort

3

foo(T const& arg) nimmt ein Referenzargument. Um ein Referenzargument durch boost::bind zu übergeben, müssen Sie es mit boost::ref umbrechen.

boost::function<T> functor2 = boost::bind(&A::foo<T>, boost::ref(arg)); 
0

Werfen sie einen Blick auf What is the return type of boost::bind?

kurz gesagt, würde ich schreiben gerade

auto functor2 = boost::bind(&A::foo<T>, arg); 

und kompilieren Sie es mit gcc 4.6+ oder mit gcc 4.4 mit --std=gnu++0x option.

+0

Leider kann ich die Option cpp0x nicht einschalten. Dieser obige Beispielcode wird vereinfacht und vom tatsächlichen Projektcode minimiert. Der Kabelbaum ist fest und kann den neuen Standard nicht verwenden. –

0

Ich habe keine Erfahrung mit Bind, aber brauchen Sie normalerweise nicht eine Instanz der Klasse, die Sie die Member-Funktion aufrufen? Wenn Sie es nicht in die Bindung einschließen, müssen Sie es an der Aufrufseite einschließen. Mit auto für mein Beispiel (ich lese über Sie nicht verwenden können, aber ich werde für Prägnanz), ich werde neu implementieren Ihre A :: bar() Methode:

void bar(T const& arg){ 
    auto barebones = boost::bind(&A::foo<T>, arg); 
    // OR 
    auto barebones = boost::bind(&A::foo<T>, _1, arg); 
    barebones(this); // Need an instance, or a pointer to an instance of A 
    boost::function<T> functor1 = boost::bind(func); // OK because func is a bare function with no arguments 
    boost::function<T> functor2 = boost::bind(&A::foo<T>, this, arg); // betting that would work 
    functor2(); // with my modification, I think that'll work. 
} 

Ebenso können Sie die _1 brauchen Syntax, um zu sagen, das erste Argument nimmt diesen Punkt, oder es kann ohne es funktionieren. Ich bin nicht 100% sicher (habe es nicht kompiliert), aber basierend auf der Dokumentation auf der Boost-Seite (Boost bind doc, Boost mem_fn doc) ist dies, was ich denke, passiert ist.

Warum der erste Teil kompiliert, weiß ich nicht. Es lässt mich vermuten, dass die ursprüngliche Syntax in Ordnung ist, aber Sie müssen die Klasseninstanz übergeben. Wenn Sie nach einem "nackten" aufrufbaren Objekt suchen, das keine zusätzlichen Argumente benötigt, müssen Sie beim Binden eine Instanz übergeben (oder einen Zeiger auf einen oder einen intelligenten Zeiger auf einen).

Wenn Sie Probleme beim Ableiten von Typen haben, versuchen Sie das BOOST_AUTO() - Makro, wenn Sie können. Doc link.