2016-05-11 7 views
1

Ich versuche, so etwas wie dies zu erreichen, aber boost binden Fehlern immerWie Boost verwenden :: korrekt mit einer Karte der Funktion binden Zeiger

#include <map> 
#include "boost/assign.hpp" 
#include <boost/foreach.hpp> 
#include <string> 
#include <boost/function.hpp> 
#include <boost/bind.hpp> 


struct myStruct_t 
{ 
    int getInt() {return 1;}; 
}; 

int foo( myStruct_t* m, std::string str) 
{ 
    if(str == "A") 
    { 
     return m->getInt(); 
    } 
    else if (str == "B") 
    { 
     return 2; 
    } 
    else 
    { 
     return 3; 
    } 
} 

typedef std::map<std::string, boost::function<int(myStruct_t*, std::string)> > Map_t; 

Map_t myMap = boost::assign::map_list_of ("Jake", boost::bind((&foo, _1), "A") 
             ("Ken", boost::bind((&foo, _1), "B") 
             ("Pete", boost::bind((&foo, _1), "C"); 



int main() 
{ 
    std::vector<std::string> myVal; 
    myVal.push_back("Jake"); 
    myVal.push_back("Ken"); 
    myVal.push_back("Pete"); 

    myStruct_t myStruct; 
    BOOST_FOREACH(const std::string& aStr, myVal) 
    { 
     Map_t::const_iterator iter = myMap.find(aStr); 
     if(iter != myMap.end()) 
     { 
      int myInt = (iter->second)(myStruct); 
     } 
    } 
    return 0; 
} 

Die Fehler, die ich sind immer bin

In file included from /usr/local/boost-1.60.0/include/boost/bind.hpp:22:0, 
       from prog.cc:6: 
/usr/local/boost-1.60.0/include/boost/bind/bind.hpp: In instantiation of 'boost::_bi::result_traits<boost::_bi::unspecified, boost::arg<1> >': 
/usr/local/boost-1.60.0/include/boost/bind/bind.hpp:1212:48: instantiated from 'boost::_bi::bind_t<boost::_bi::unspecified, boost::arg<1>, boost::_bi::list1<boost::_bi::value<const char*> > >' 
prog.cc:32:81: instantiated from here 
/usr/local/boost-1.60.0/include/boost/bind/bind.hpp:75:37: error: no type named 'result_type' in 'struct boost::arg<1>' 
prog.cc:34:82: error: expected ')' before ';' token 
prog.cc: In function 'int main()': 
prog.cc:50:48: error: no match for call to '(const boost::function<int(myStruct_t*, std::basic_string<char>)>) (myStruct_t&)' 
/usr/local/boost-1.60.0/include/boost/function/function_template.hpp:765:17: note: candidate is: result_type boost::function2<R, T1, T2>::operator()(T0, T1) const [with R = int, T0 = myStruct_t*, T1 = std::basic_string<char>, result_type = int] 

Es scheint, ich bin verwirrt, wie boost :: bind verwendet wird. Kann mir bitte jemand helfen, es richtig zu machen? Danke vielmals.

+0

Sie haben einen zusätzlichen Satz von Klammern in 'boost :: bind ((& foo, _1), "A") 'und all die anderen. Entferne sie. –

+0

Der Typ von 'Map' sollte auch' boost :: function ' –

+0

Die zusätzliche Klammer entfernt und die Map in boost :: function geändert. Immer noch den Fehler – polapts

Antwort

2

Die Funktion Signatur am Aufrufstelle erwartet ist int (myStruct *)

wegen dieser Linie (I die & hinzugefügt einen Logikfehler zu entfernen):

int myInt = (iter->second)(&myStruct); 

in welchem ​​Fall die Erklärung der Karte sollte sein:

typedef std::map<std::string, boost::function<int(myStruct_t*)> > Map_t; 

Map_t myMap = boost::assign::map_list_of 
("Jake", boost::bind(&foo, boost::placeholders::_1, std::string("A"))) 
("Ken", boost::bind(&foo, boost::placeholders::_1, std::string("B"))) 
("Pete", boost::bind(&foo, boost::placeholders::_1, std::string("C"))); 

Und dann sind Sie gut zu gehen.

Erklärung:

boost [std] :: bind liefert ein Funktionsobjekt, das nur die Parameter akzeptieren ausgelegt ist, die als Platzhalter in dem bind Ausdruck genannt werden.

Dies bedeutet, dass die Funktion, die schließlich oft mehr Argumente haben als die Funktion Objekt durch bind

so in Ihrem Fall wieder aufgerufen wird, foo die folgende Signatur hat:

int foo( myStruct_t* m, std::string str) 

dh nimmt zwei Argumente und gibt ein int zurück.

jedoch an der Stelle des Aufrufs bind.

boost::bind(&foo, boost::placeholders::_1, std::string("A")) 

Was wir sagen, ist „foo und das zweite Argument der Funktion erfassen (String) Gibt mir ein Funktionsobjekt, das ein Argument erfordert (_1) und leitet dieses Argument als erstes Argument zu foo während das gebundene Zeichenkette als das zweite Argument übergeben

so gegeben:.

auto f = boost::bind(&foo, boost::placeholders::_1, std::string("A")); 

f hat die Unterschrift int f(MyStruct*)

und wenn sie mit

auto i = f(&mystruct); 

genannt ist es gleichbedeutend mit Aufruf:

auto i = foo(&mystruct, std::string("A")); 
+0

Vielen Dank. Es hat gut funktioniert.Ich kann ein Problem verstehen, dass die Funktion einen Zeiger erwartete und ich ein Objekt passierte. Aber die Funktion int foo (myStruct_t * m, std :: string str) erwartet zwei Parameter myStruct_t und std :: string. Warum hat dann die boost :: function nur einen Parameter in der Deklaration? – polapts

+0

@polaps aktualisiert mit einer längeren Erklärung. Hoffe, das ist nützlich. –

+0

Excellet! Danke vielmals. – polapts