Consider the following (https://godbolt.org/z/sfT3aesvK):
#include <utility>
#include <vector>
struct A { constexpr static int type = 0; };
template <typename Func, typename... Args>
int foo(Func func, Args&& ... args) {
auto call_with_A = [func](Args&& ... args) {
return func.template operator()<A>(std::forward<Args>(args)...);
};
std::vector<int(*)(Args&&...) /* what goes here? */> vec{{call_with_A}};
int acc = 0;
for (auto fn : vec) {
acc += fn(std::forward<Args>(args)...);
}
return acc;
}
int bar() {
return 1 + foo([]<typename T>(int a, int b) {
return T::type + a + b;
}, 2, 3);
}
The above does not compile, because
no known conversion from '(lambda at <source>:8:24)' to 'int (*)(int &&, int &&)' for 1st argument
My question is what the template type T
so that std::vector<T>
will accept call_with_A
as an element?
I tried to print what decltype(call_with_A)
is, but this seems to just be a (lambda at [...])
expression for the compiler.
The type of a lambda expression is "unutterable". It cannot be written down directly. However, you can declare a typedef
alias for the type:
auto call_with_A = /* lambda */;
using LambdaType = decltype(call_with_A);
std::vector<LambdaType> vec = {call_with_A};
You can also use class template argument deduction if you don't need to mention the type anyway:
auto call_with_A = /* lambda */;
std::vector vec = {call_with_A};
// the type of `vec` is `std::vector<decltype(call_with_A)>`