Passando um objeto função: Erro
-
22-08-2019 - |
Pergunta
O que há de errado com o pequeno programa seguinte que passa um objeto de função?
#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;
}
Estou recebendo o seguinte erro na linha 6:
no match for call to
`(const std::unary_function<const std::string&, void>) (const std::string&)'
Solução
Um erro comum. unary_function
e binary_function
são apenas duas estruturas que agregam typedefs
argument_type
result_type
e respectivamente
first_argument_type
second_argument_type
result_type
Não mais. Eles são para conveniência de criadores de tipos de função de objeto, para que eles não têm que fazer os mesmos. Mas eles não se comportam polimórfico. O que você quer é função wrapper objeto. boost::function
vem à mente:
void foo(boost::function<void(const std::string&)> const& fct) {
const std::string str = "test";
fct(str); // no error anymore
}
Ou torná-lo um modelo
template<typename FunctionObject>
void foo(FunctionObject const& fct) {
const std::string str = "test";
fct(str); // no error anymore
}
Você pode levá-lo por valor e, em seguida, retornar a cópia de foo
se usá-lo para aplicá-la a uma sequência. O que permitiria que o objeto função para atualizar algumas variáveis ??de estado entre os seus membros. for_each
é um exemplo que faz isso assim. Geralmente, de qualquer maneira, eu iria aceitá-los por valor, porque eles são geralmente pequenas e copiá-los permite uma maior flexibilidade. Então eu faço
template<typename FunctionObject>
void foo(FunctionObject fct) {
const std::string str = "test";
fct(str); // no error anymore
}
Você será capaz de tirar uma cópia da FCT e salvá-lo em algum lugar, e operador de fct
() pode ser não-const e atualizar alguns membros (que faz parte de todo o ponto de operator()
). Lembre-se você tomar um objeto de função por referência const, você geralmente não pode copiá-lo, porque o usuário poderia ter passado uma função. Copiá-lo, em seguida, vai tentar declarar localmente uma função em vez de um ponteiro de função local. No entanto, aceitando por valor irá aceitar um ponteiro de função em vez quando uma função foi aprovada, o que pode seguramente ser copiado.