Übergeben eines Funktionsobjekt: Fehler
-
22-08-2019 - |
Frage
Was ist los mit dem folgenden kleinen Programm, das eine Funktion Objekt passiert?
#include <iostream>
#include <functional>
void foo(const std::unary_function<const std::string&, void>& fct) {
const std::string str = "test";
fct(str); // error
}
class MyFct : public std::unary_function<const std::string&, void> {
public:
void operator()(const std::string& str) const {
std::cout << str << std::endl;
}
};
int main(int argc, char** argv){
MyFct f;
foo(f);
return 0;
}
Ich erhalte die folgenden Fehler in Zeile 6:
no match for call to
`(const std::unary_function<const std::string&, void>) (const std::string&)'
Lösung
Ein häufiger Fehler. unary_function
und binary_function
sind nur zwei Strukturen, die typedefs
argument_type
result_type
bzw.
first_argument_type
second_argument_type
result_type
Nicht mehr. Sie sind für die Bequemlichkeit der Schöpfer der Funktion Objekttypen, so dass sie nicht über jene selbst zu tun. Aber sie verhalten sich nicht polymorph. Was Sie wollen, ist Funktion Objekt-Wrapper. boost::function
in den Sinn kommt:
void foo(boost::function<void(const std::string&)> const& fct) {
const std::string str = "test";
fct(str); // no error anymore
}
Oder machen Sie es sich um eine Vorlage
template<typename FunctionObject>
void foo(FunctionObject const& fct) {
const std::string str = "test";
fct(str); // no error anymore
}
Sie können es von Wert nehmen und dann die Kopie von foo
zurück, wenn es verwenden, um es irgendeine Reihenfolge anzuwenden. Was die Funktion Objekt erlauben würde, einige Zustandsvariablen unter seinen Mitgliedern zu aktualisieren. for_each
ist ein Beispiel, das es so tut. Im Allgemeinen wie auch immer, würde ich sie von Wert annehmen, weil sie in der Regel klein sind und sie ermöglichen das Kopieren von mehr Flexibilität. Also ich tun
template<typename FunctionObject>
void foo(FunctionObject fct) {
const std::string str = "test";
fct(str); // no error anymore
}
Sie erhalten dann eine Kopie von fct nehmen können und es irgendwo speichern und fct
des Betreibers () kann nicht const sein und einige Mitglieder aktualisieren (die Teil des ganzen Punkt von operator()
ist). Denken Sie daran, wenn Sie eine Funktion Objekt durch konstante Referenz nehmen, können Sie im Allgemeinen nicht kopieren, weil der Benutzer eine Funktion übergeben konnte. Kopieren sie dann versuchen, lokal deklarieren eine Funktion statt einer lokalen Funktionszeiger. Jedoch durch-Wert zu übernehmen einen Funktionszeiger stattdessen akzeptieren, wenn eine Funktion übergeben wurde, was sicher kopiert werden kann.