2009-03-29 8 views
4

Quel est le problème avec le petit programme suivant qui réussit un objet fonction?Passage d'un objet fonction: Erreur

#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&)' 

Répondre

11

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 n'ont pas à faire eux-mêmes. Mais ils ne se comportent pas polymorphique. Ce que vous voulez, c'est un wrapper d'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 fonction de mettre à jour certaines variables d'état parmi ses membres. for_each est un exemple qui le fait comme ça. Généralement, de toute façon, je les accepterais en valeur car ils sont généralement petits et les copier permet une plus grande flexibilité. Donc, je ne

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 non-const et mettre à jour certains membres (qui fait partie du point entier de operator()). Souvenez-vous que si vous prenez un objet fonction par référence const, vous ne pouvez généralement pas le copier, car l'utilisateur aurait pu passer une fonction. La copier puis essaiera de déclarer localement une fonction au lieu d'un pointeur de fonction local. Cependant, l'acceptation de la valeur par défaut accepte un pointeur de fonction à la place d'une fonction qui peut être copiée en toute sécurité.

+0

Merci pour votre réponse! La solution boost est-elle aussi efficace que la solution template? – Frank

+0

la solution boost n'est pas aussi efficace, car elle doit faire un appel indirect à l'objet fonction enveloppé (elle crée sa propre vtable pour cela). Mais il a l'avantage de ne pas avoir besoin de modèle. vous pouvez simplement utiliser cette fonction boost.function et la stocker quelque part (par exemple en tant que membre de la classe). –

+0

Je pense qu'il est le plus proche de ce que vous avez cherché avec unary_function –

Questions connexes