Reputation: 4481
I have seen how to declare a vector of functions (see calling a function from a vector).
But that answer users pointers. How can I create a vector of functions/lambdas using the new syntax in modern C++?
the examples of functions using the new syntax typically use auto:
auto f = [] (std::string msg) -> void {
std::cout << msg << std::endl;
};
What is the actual type of f? so I can declare a vector of this type?
thank you very much for any help
Upvotes: 8
Views: 7403
Reputation: 13988
As mentioned each lambda you declare has unique context specific type even if it has seemingly identical signature. This is why vector of lambdas has only theoretical value - you would be able to push there at most one lambda... You have two choices - you could go along with proposed approach from other answers and store lambdas into a type-erasure std::function
before putting them into vector or put your lambdas into a "container" that would collect the type of each element apart from the lambda object itself - std::tuple
:
auto t = std::make_tuple([](){ std::cout<<"First lambda" << std::endl; },
[](){ std::cout<<"Second lambda"<< std::endl; },
[](){ std::cout<<"Third lambda" << std::endl; });
and get appropriate lambda at compile-time:
std::get<0>(t)(); // the value in get must be known at compile time!
// otherwise compiler won't be able to establish type
// of lambda and the whole point of using tuple is lost
Upvotes: 2
Reputation: 206697
What is the actual type of
f
? so I can declare a vector of this type?
Type of f
can only be deduced by using auto
. You can declare a vector
of this type using
std::vector<decltype(f)> v;
However, it is not very useful. Lambda functions that look strikingly similar have different types. To make matters worse, lambda functions that have identical body also have different types.
auto f = [] (std::string msg) -> void {
std::cout << msg << std::endl;
};
auto g = [] (std::string msg) -> void {
std::cout << msg << std::endl;
};
auto h = [] (std::string msg) -> void {
std::cout << msg << '+' << msg << std::endl;
};
Given the above functions, you can't use
std::vector<decltype(f)> v;
v.push_back(f); // OK
v.push_back(g); // Not OK
v.push_back(h); // Not OK
Your best option is to create a std::vector
of std::function
s. You can add the lambda functions to that std::vector
. Given the above definitions of f
and g
, you can use:
std::vector<std::function<void(std::string)>> v;
v.push_back(f);
v.push_back(g);
v.push_back(h);
Upvotes: 10
Reputation: 29966
Use std::function
with the corresponding type:
std::vector<std::function<void(void)>> vec;
vec.push_back([]()->void{});
In your case it would be std::function<void(std::string)>
.
The exact type of a lambda is meaningless per standard ([expr.prim.lambda]/3):
The type of the lambda-expression (which is also the type of the closure object) is a unique, unnamed non-union class type
Upvotes: 15