It is necessary for 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?
It is necessary for 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?
Let's break the line apart:
std::function
This is a declaration for a function taking no parameters, and returning no value. If the function returned an int
, it would look like this:
std::function<int()>
Likewise, if it took an int parameter as well:
std::function<int(int)>
I suspect your main confusion is the next part.
[]() { FNAME(); };
The []
part is called a capture clause. Here you put variables that are local to the declaration of your lambda, and that you want to be available within the lambda function itself. This is saying "I don't want anything to be captured". If this was within a class definition and you wanted the class to be available to the lambda, you might do:
[this]() { FNAME(); };
The next part, is the parameters being passed to the lambda, exactly the same as if it was a regular function. As mentioned earlier, std::function<void()>
is a signature pointing to a method that takes no parameters, so this is empty also.
The rest of it is the body of the lambda itself, as if it was a regular function, which we can see just calls the function FNAME
.
Another Example
Let's say you had the following signature, that is for something that can sum two numbers.
std::function<int(int, int)> sumFunc;
We could now declare a lambda thusly:
sumFunc = [](int a, int b) { return a + b; };
Not sure if you're using MSVC, but here's a link anyway to the lamda expression syntax:
Lambdas with captures (stateful lambdas) cannot be assigned to each other since they have unique types, even if they look exactly the same. To be able to store and pass around lambdas with captures, we can use "std::function" to hold a function object constructed by a lambda expression. Basically "std::function" is, to be able to assign lambda functions with different content structures to a lambda function object.
Exp :
auto func = [](int a){
cout << "a:" << a << endl;
};
func(40);
//
int x = 10;
func = [x](int a){ //ATTENTION(ERROR!): assigning a new structure to the same object
cout << "x:" << x << ",a:" << a << endl;
};
func(2);
So the above usage will be incorrect. But if we define a function object with "std::function":
auto func = std::function<void(int)>{};
func = [](int a){
cout << "a:" << a << endl;
};
func(40);
//
int x = 10;
func = [x](int a){ //CORRECT. because of std::function
//...
};
int y = 11;
func = [x,y](int a){ //CORRECT
//...
};
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. Forstd::function
, the primary1 operations are copy/move, destruction, and 'invocation' withoperator()
-- 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 twoint
arguments and returnsdouble
. 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 astd::function
at the cost of some run time overhead.[](){ code }
in particular is a really simple lambda. It corresponds to this: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 (prior to c++20) looks like:
By c++23, the syntax expanded to:
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.basically becomes
Note that in c++20 template arguments were added to lambdas, and that isn't covered above.
and attributes c++20 and requires clauses c++23 also can be used with lambdas.
Template arguments after the
[]
apply to theoperator()
and not the lambda as a whole. Ie:is a
template
variable, whileis a variable with a
template
operator()
.1 In addition, RTTI is stored (typeid), and the cast-back-to-original-type operation is included.