What's wrong with the following little program that passes a function object?
#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;
}
I'm getting the following error in line 6:
no match for call to
`(const std::unary_function<const std::string&, void>) (const std::string&)'
A common mistake. unary_function
and binary_function
are just two structs that add typedefs
argument_type
result_type
and respectively
first_argument_type
second_argument_type
result_type
Not more. They are for convenience of creators of function object types, so they don't have to do those themselves. But they don't behave polymorphic. What you want is function object wrapper. boost::function
comes to mind:
void foo(boost::function<void(const std::string&)> const& fct) {
const std::string str = "test";
fct(str); // no error anymore
}
Or make it a template
template<typename FunctionObject>
void foo(FunctionObject const& fct) {
const std::string str = "test";
fct(str); // no error anymore
}
You can take it by value and then return the copy from foo
if use it to apply it to some sequence. Which would allow the function object to update some state variables among its members. for_each
is an example that does it like that. Generally, anyway, i would accept them by value because they are usually small and copying them allows greater flexibility. So i do
template<typename FunctionObject>
void foo(FunctionObject fct) {
const std::string str = "test";
fct(str); // no error anymore
}
You will then be able to take a copy of fct and save it somewhere, and fct
's operator() can be non-const and update some members (which is part of the whole point of operator()
). Remember if you take a function object by const reference, you can't generally copy it, because the user could have passed a function. Copying it then will try to locally declare a function instead of a local function pointer. However, accepting by-value will accept a function pointer instead when a function was passed, which can safely be copied.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With