Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Function objects in C++ (C++11)

I am reading about boost::function and I am a bit confused about its use and its relation to other C++ constructs or terms I have found in the documentation, e.g. here.

In the context of C++ (C++11), what is the difference between an instance of boost::function, a function object, a functor, and a lambda expression? When should one use which construct? For example, when should I wrap a function object in a boost::function instead of using the object directly?

Are all the above C++ constructs different ways to implement what in functional languages is called a closure (a function, possibly containing captured variables, that can be passed around as a value and invoked by other functions)?

like image 914
Giorgio Avatar asked Oct 10 '12 13:10

Giorgio


People also ask

What is a function object in C?

A function object, or functor, is any type that implements operator(). This operator is referred to as the call operator or sometimes the application operator. The C++ Standard Library uses function objects primarily as sorting criteria for containers and in algorithms.

What is the object of a function?

A Function Object, or Functor (the two terms are synonymous) is simply any object that can be called as if it is a function. An ordinary function is a function object, and so is a function pointer; more generally, so is an object of a class that defines operator().

What is function object in oops?

In computer programming, a function object is a construct allowing an object to be invoked or called as if it were an ordinary function, usually with the same syntax (a function parameter that can also be a function). Function objects are often called functors.

Is a functor a function?

A functor, also known as a function object, is an object that is able to be called as if it were a function. In C++, we do this by overloading the function call operator -- operator() -- which is the one special operator that does not fit into the "binary" or "unary" classification of operators.


2 Answers

A function object and a functor are the same thing; an object that implements the function call operator operator(). A lambda expression produces a function object. Objects with the type of some specialization of boost::function/std::function are also function objects.

Lambda are special in that lambda expressions have an anonymous and unique type, and are a convenient way to create a functor inline.

boost::function/std::function is special in that it turns any callable entity into a functor with a type that depends only on the signature of the callable entity. For example, lambda expressions each have a unique type, so it's difficult to pass them around non-generic code. If you create an std::function from a lambda then you can easily pass around the wrapped lambda.

like image 180
bames53 Avatar answered Sep 28 '22 07:09

bames53


Both boost::function and the standard version std::function are wrappers provided by the li­brary. They're potentially expensive and pretty heavy, and you should only use them if you actually need a collection of heterogeneous, callable entities. As long as you only need one callable entity at a time, you are much better off using auto or templates.

Here's an example:

std::vector<std::function<int(int, int)>> v;

v.push_back(some_free_function);           // free function
v.push_back(&Foo::mem_fun, &x, _1, _2);    // member function bound to an object
v.push_back([&](int a, int b) -> int { return a + m[b]; });  // closure

int res = 0;
for (auto & f : v) { res += f(1, 2); }

Here's a counter-example:

template <typename F>
int apply(F && f)
{
    return std::forward<F>(f)(1, 2);
}

In this case, it would have been entirely gratuitous to declare apply like this:

int apply(std::function<int(int,int)>)   // wasteful

The conversion is unnecessary, and the templated version can match the actual (often unknowable) type, for example of the bind expression or the lambda expression.

like image 23
Kerrek SB Avatar answered Sep 28 '22 05:09

Kerrek SB