Usage and Syntax of std::function

user2982229 picture user2982229 · Dec 3, 2013 · Viewed 62.2k times · Source

It is necessary to me to use std::function but I don't know what the following syntax means.

std::function<void()> f_name = []() { FNAME(); };

What is the goal of using std::function? Is it to make a pointer to a function?

Answer

Yakk - Adam Nevraumont picture Yakk - Adam Nevraumont · Dec 3, 2013

std::function is a type erasure object. That means it erases the details of how some operations happen, and provides a uniform run time interface to them. For std::function, the primary1 operations are copy/move, destruction, and 'invocation' with operator() -- the 'function like call operator'.

In less abstruse English, it means that std::function can contain almost any object that acts like a function pointer in how you call it.

The signature it supports goes inside the angle brackets: std::function<void()> takes zero arguments and returns nothing. std::function< double( int, int ) > takes two int arguments and returns double. In general, std::function supports storing any function-like object whose arguments can be converted-from its argument list, and whose return value can be converted-to its return value.

It is important to know that std::function and lambdas are different, if compatible, beasts.

The next part of the line is a lambda. This is new syntax in C++11 to add the ability to write simple function-like objects -- objects that can be invoked with (). Such objects can be type erased and stored in a std::function at the cost of some run time overhead.

[](){ code } in particular is a really simple lambda. It corresponds to this:

struct some_anonymous_type {
  some_anonymous_type() {}
  void operator()const{
    code
  }
};

an instance of the above simple pseudo-function type. An actual class like the above is "invented" by the compiler, with an implementation defined unique name (often including symbols that no user-defined type can contain) (I do not know if it is possible that you can follow the standard without inventing such a class, but every compiler I know of actually creates the class).

The full lambda syntax looks like:

[ capture_list ]( argument_list )
-> return_type optional_mutable
{
  code
}

But many parts can be omitted or left empty. The capture_list corresponds to both the constructor of the resulting anonymous type and its member variables, the argument_list the arguments of the operator(), and the return type the return type. The constructor of the lambda instance is also magically called when the instance is created with the capture_list.

[ capture_list ]( argument_list ) -> return_type { code }

basically becomes

struct some_anonymous_type {
  // capture_list turned into member variables
  some_anonymous_type( /* capture_list turned into arguments */ ):
    /* member variables initialized */
  {}
  return_type operator()( argument_list ) const {
    code
  }
};

Note that in template arguments were added to lambdas, and that isn't covered above.

[]<typename T>( std::vector<T> const& v ) { return v.size(); }

1 In addition, RTTI is stored (typeid), and the cast-back-to-original-type operation is included.