2009-07-08 8 views
2

Wie kann ich das kompilieren? Der Fehler ist, wenn ich boost :: ref() benutze. Ich dachte boost :: ref wird verwendet, um Verweis auf C++ - Algorithmus-Klassen zu übergeben?Verwendung von Boost :: ref korrekt ..?

list<Object> lst; 
    lst.push_back(Object(1,2.0f)); 
    lst.push_back(Object(3,4.3f)); 

    struct between_1_and_10 
    { 
    int d; 
    void operator() (Object& value) 
    { 
     value.a += 5; value.b -= 3.3f; 
     cout << d << endl; 
     d += value.a; 
    } 
    }; 

    between_1_and_10 val; 
    val.d = 4; 
    for_each(lst.begin(), lst.end(), boost::ref(val)); // Problem is here 
    printf("rg"); 

EDIT Hier ist der Compiler-Fehler als Menschen vorgeschlagen:

1>c:\program files (x86)\microsoft visual studio 9.0\vc\include\algorithm(29) : error C2064: term does not evaluate to a function taking 1 arguments 
1>  c:\users\swangrun\desktop\minescout work\feat-000-gettargetimages\minescouttest\maintest.cpp(102) : see reference to function template instantiation '_Fn1 std::for_each<std::list<_Ty>::_Iterator<_Secure_validation>,boost::reference_wrapper<T>>(_InIt,_InIt,_Fn1)' being compiled 
1>  with 
1>  [ 
1>   _Fn1=boost::reference_wrapper<main::between_1_and_10>, 
1>   _Ty=Object, 
1>   _Secure_validation=true, 
1>   T=main::between_1_and_10, 
1>   _InIt=std::list<Object>::_Iterator<true> 
1>  ] 
+0

Ok. Es sollte auf der for_each() Zeile sein. Aber was ist das Problem? Sie müssen uns entweder den Fehler oder genügend Code geben, damit wir den Fehler reproduzieren können. –

+0

das Problem ist, dass es nicht kompiliert. Ich habe eine Antwort angenommen, danke für Ihre Teilnahme! – sivabudh

+0

Was Martin meinte, ist "Kopiere den Text der Fehlermeldung und füge ihn in deine Frage ein". Auf diese Weise können wir Ihnen erklären, was der Compiler sagt. Es gab Ihnen wahrscheinlich alle Informationen, die Sie benötigen, um den Fehler zu finden.Zumindest sollten Sie dies tun, damit andere Leute, die nach dem Text des Compilerfehlers suchen, die Frage und ihre Antwort finden können. –

Antwort

7

was Sie wirklich wollen:

for_each(lst.begin(), lst.end(), boost::bind<void>(boost::ref(val),_1 )); 

EDIT: Eine Erklärung auf Wunsch des OP. Denken Sie daran, dass for_each() eine Funktion übernimmt, aber Sie haben lediglich einen Verweis auf Ihre Struktur übergeben (ja, die Struktur hat ihren Operator() überladen, aber Sie haben das nicht übergeben). bind() im Grunde "exposed" die Funktion in Ihrer Struktur.

EDIT2: Erklärung der "_1" kann in den Kommentaren unten gefunden werden.

+0

danke. Genau das, was ich gesucht habe. Wenn es nicht zu mühsam ist, könnten Sie bitte erläutern, warum die Bindung notwendig ist ... und was ist das komisch aussehende _1? Es tut mir leid, ich bin neu bei Boost. (Es sei denn natürlich, es gibt ein gutes Tutorial irgendwo von den Techniken, die Sie gerade verwendet haben.) – sivabudh

+1

Bindung ist wahrscheinlich notwendig, weil der Compiler den Rückgabetyp der Funktion nicht abgeleitet in boost: ref. Wie für die "_1", können Sie hier darüber lesen: http://www.boost.org/doc/libs/1_39_0/libs/bind/bind.html#with_functions –

+0

-1, der _1 ist der Lambda-Platzhalter. Es stellt tatsächlich das "aktuelle" Element dar, auf das der Iterator von for_each zeigt. – paxos1977

-1

Probieren Sie es ohne die boost :: ref. Diese

12

boost::reference_wrapper (was boost::ref zurückgibt) überlädt nicht operator(). Sie können es mit boost::bind verwenden, die spezielle Behandlung dafür hat (nicht ref verwendend, würde bind das bereitgestellte Funktionsobjekt kopieren).

Aber for_each gibt das Funktionsobjekt zurück, auf das es das Zeug aufruft. So tun nur das

between_1_and_10 val; 
val.d = 4; 
val = for_each(lst.begin(), lst.end(), val); 
printf("rg"); 

Es wird das Material auf dem kopiert val rufen, und senden Sie das Funktionsobjekt, wie es nach dem letzten Aufruf ist.


einfach zu sagen, wo Sie boost::ref verwenden können, weil Sie es zu missbrauchen scheinen. Stellen Sie sich eine Vorlage, die ihre Parameter von Wert annimmt, und ruft eine andere Funktion:

void g(int &i) { i++; } 

template<typename T> 
void run_g(T t) { g(t); } 

Wenn Sie es jetzt mit einer variablen nennen wollen, es wird es kopieren. Das ist oft eine vernünftige Entscheidung. Wenn Sie beispielsweise Daten als Startparameter an einen Thread übergeben möchten, können Sie sie aus Ihrer lokalen Funktion in das Thread-Objekt kopieren. Aber manchmal könnten Sie es nicht kopieren wollen, sondern eine Referenz übergeben. Hier hilft boost::reference_wrapper. Die folgende tatsächlich tut, was wir erwarten, und Ausgänge 1:

int main() { 
    int n = 0; 
    run_g(boost::ref(n)); 
    std::cout << n << std::endl; 
} 

Für verbindliche Argumente, eine Kopie ist ein guter Standard. Es macht auch leicht, dass Arrays und Funktionen zu Zeigern zerfallen (das Akzeptieren als Referenz würde T möglicherweise zu einem Array/Funktionstyp machen und würde einige unangenehme Probleme verursachen).

Verwandte Themen