带参数包的lambda类型



考虑以下内容(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);
}

上面的代码不能编译,因为

no known conversion from '(lambda at <source>:8:24)' to 'int (*)(int &&, int &&)' for 1st argument

我的问题是模板类型T是什么,以便std::vector<T>将接受call_with_A作为元素?

我试图打印decltype(call_with_A)是什么,但这似乎只是编译器的(lambda at [...])表达式。

lambda表达式的类型为" unutterable";不能直接写下来。但是,您可以为类型声明一个typedef别名:

auto call_with_A = /* lambda */;
using LambdaType = decltype(call_with_A);
std::vector<LambdaType> vec = {call_with_A};

如果不需要提及类型,也可以使用类模板参数推导:

auto call_with_A = /* lambda */;
std::vector vec = {call_with_A};
// the type of `vec` is `std::vector<decltype(call_with_A)>`

每个lambda都有一个不同类型的-即使他们有相同的签名。具有相同函数体的Lambda函数也具有不同的类型。

可以使用decltype声明vector类型。然而,它是没有用的。例如,

template <typename Func, typename... Args>
int foo(Func func, Args&& ... args) {
auto call_with_A = [func](Args&& ... args) {
return func.template operator()<A1>(std::forward<Args>(args)...);
};
auto call_with_A1 = [func](Args&& ... args) {
return func.template operator()<A1>(std::forward<Args>(args)...);
};
auto call_with_A2 = [func](Args&& ... args) {
return func.template operator()<A1>(std::forward<Args>(args)...);
};
std::vector<decltype(call_with_A)> vec;
vec.push_back(call_with_A);
vec.push_back(call_with_A1); // Not OK
vec.push_back(call_with_A2); // Not OK

return 0;
}

您最好的选择是使用std::functionstd::vector。例如,

template <typename Func, typename... Args>
int foo(Func func, Args&& ... args) {
auto call_with_A = [func](Args&& ... args) {
return func.template operator()<A1>(std::forward<Args>(args)...);
};
auto call_with_A1 = [func](Args&& ... args) {
return func.template operator()<A1>(std::forward<Args>(args)...);
};
auto call_with_A2 = [func](Args&& ... args) {
return func.template operator()<A1>(std::forward<Args>(args)...);
};

std::vector<std::function<int(Args...)>> vec;
vec.push_back(call_with_A);
vec.push_back(call_with_A1);
vec.push_back(call_with_A2);

return 0;
}

最新更新