Распространенная ошибка. unary_function
и binary_function
- это всего лишь две структуры, которые добавляют typedefs
argument_type
result_type
и соответственно
first_argument_type
second_argument_type
result_type
Не более. Они для удобства создателей типов функциональных объектов, поэтому им не нужно делать это самим. Но они не ведут себя полиморфно. То, что вы хотите, это обертка объекта функции. boost::function
приходит на ум:
void foo(boost::function<void(const std::string&)> const& fct) {
const std::string str = "test";
fct(str); // no error anymore
}
Или создайте шаблон
template<typename FunctionObject>
void foo(FunctionObject const& fct) {
const std::string str = "test";
fct(str); // no error anymore
}
Вы можете взять его по значению, а затем вернуть копию из foo
, если используете ее для применения к некоторой последовательности. Что позволило бы объекту функции обновить некоторые переменные состояния среди его членов. for_each
пример, который делает это так. В общем, в любом случае, я бы принял их по значению, потому что они, как правило, маленькие, и их копирование обеспечивает большую гибкость. Так что я делаю
template<typename FunctionObject>
void foo(FunctionObject fct) {
const std::string str = "test";
fct(str); // no error anymore
}
После этого вы сможете взять копию функции fct и сохранить ее где-нибудь, а оператор fct
() может быть неконстантным и обновлять некоторые элементы (что является частью всего пункта operator()
) , Помните, что если вы берете объект функции по константной ссылке, вы обычно не можете скопировать его, потому что пользователь мог передать функцию. Затем, копируя его, вы попытаетесь локально объявить функцию вместо указателя на локальную функцию. Однако принятие by-value примет функцию указателя вместо того, чтобы передать функцию, которую можно безопасно скопировать.