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&)'
Était-ce utile?

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é.

Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top