Le passage d'un objet de fonction: Erreur
-
22-08-2019 - |
Question
Quel est le problème avec le petit programme suivant qui passe un objet de fonction?
#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;
}
Je reçois l'erreur suivante dans la ligne 6:
no match for call to
`(const std::unary_function<const std::string&, void>) (const std::string&)'
La solution
Une erreur commune. unary_function
et binary_function
ne sont que deux struct qui ajoutent typedefs
argument_type
result_type
et respectivement
first_argument_type
second_argument_type
result_type
Pas plus. Ils sont pour la commodité des créateurs de types d'objets de fonction, de sorte qu'ils ne doivent pas faire eux-mêmes ceux-ci. Mais ils ne se comportent pas polymorphes. Qu'est-ce que vous voulez est wrapper objet fonction. boost::function
vient à l'esprit:
void foo(boost::function<void(const std::string&)> const& fct) {
const std::string str = "test";
fct(str); // no error anymore
}
Ou faire un modèle
template<typename FunctionObject>
void foo(FunctionObject const& fct) {
const std::string str = "test";
fct(str); // no error anymore
}
Vous pouvez le prendre par valeur, puis retourner la copie de foo
si l'utiliser pour l'appliquer à une certaine séquence. Ce qui permettrait à l'objet de la fonction de mise à jour des variables d'état parmi ses membres. for_each
est un exemple comme le fait. En général, de toute façon, je les accepte en valeur parce qu'ils sont généralement de petite taille et les copier permet une plus grande flexibilité. Donc, je fais
template<typename FunctionObject>
void foo(FunctionObject fct) {
const std::string str = "test";
fct(str); // no error anymore
}
Vous serez alors en mesure de prendre une copie de fct et enregistrez quelque part, et l'opérateur de fct
() peut être mettre à jour certains membres et non-const (qui fait partie du point entier de operator()
). Rappelez-vous si vous prenez un objet de fonction par référence const, vous ne pouvez pas copier en général, parce que l'utilisateur aurait pu passer une fonction. Copier puis essayera de déclarer localement une fonction au lieu d'un pointeur de fonction locale. Toutefois, l'acceptation par valeur acceptera un pointeur de fonction au lieu lorsqu'une fonction a été adoptée, ce qui peut être copié en toute sécurité.