从C ++ 14开始,我们可以使用泛型lambdas:
auto generic_lambda = [] (auto param) {};
这基本上意味着它的调用操作符基于标记为auto的参数进行模板化。
问题是如何创建一个可以接受可变参数数量的lambda,类似于可变参数函数模板的工作方式?如果这不可能,最接近的东西可以用同样的方法吗?你会怎么存储它?是否有可能在std::function
?
我不确定你的意图是什么,但不是将它存储在std::function
中,你可以使用lambda本身捕获params。这是在boost邮件列表中讨论的示例。它用于boost::hana实现
auto list = [](auto ...xs) {
return [=](auto access) { return access(xs...); };
};
auto head = [](auto xs) {
return xs([](auto first, auto ...rest) { return first; });
};
auto tail = [](auto xs) {
return xs([](auto first, auto ...rest) { return list(rest...); });
};
auto length = [](auto xs) {
return xs([](auto ...z) { return sizeof...(z); });
};
// etc...
// then use it like
auto three = length(list(1, '2', "3"));
你如何创建一个可变的通用lambda?
您可以使用以下语法创建可变参数通用lambda:
auto variadic_generic_lambda = [] (auto... param) {};
基本上你只需在...
(可能是ref qualified)和你的参数包名称之间添加auto
。
所以通常使用通用引用会给出:
auto variadic_generic_lambda = [] (auto&&... param) {};
你如何使用这些参数?
您应该将variadic泛型参数视为具有模板参数包类型,因为它就是这种情况。这或多或少意味着大多数(如果不是全部)这些参数的使用将需要模式以这种方式或另一种方式。
这是一个典型的例子:
#include <iostream>
void print(void)
{
}
template <typename First, typename ...Rest>
void print(const First& first, Rest&&... Args)
{
std::cout << first << std::endl;
print(Args...);
}
int main(void)
{
auto variadic_generic_lambda = [] (auto... param)
{
print(param...);
};
variadic_generic_lambda(42, "lol", 4.3);
}
你如何存储一个可变的通用lambda?
你可以使用auto
将lambda存储在它自己类型的变量中,或者你可以将它存储在std::function
中,但是你只能使用你给std::function
的固定签名来调用它:
auto variadic_generic_lambda = [] (auto... param) {};
std::function<void(int, int)> func = variadic_generic_lambda;
func(42, 42); // Compiles
func("lol"); // Doesn't compile
可变系列通用lambda的集合怎么样?
由于每个lambda具有不同的类型,因此您无法将其直接类型存储在STL的通常的同类容器中。使用非泛型lambdas的方法是将它们存储在相应的std::function
中,该auto non_generic_lambda_1 = [] (int, char) {};
auto non_generic_lambda_2 = [] (int, char) {};
std::vector<std::function<void(int, char)>> vec;
vec.push_back(non_generic_lambda_1);
vec.push_back(non_generic_lambda_2);
将具有固定的签名调用,并且不会限制任何内容,因为您的lambda首先不是通用的,并且只能以这种方式调用:
std::vector<boost::variant>
如本存储部分的第一部分所述,如果您可以限制自己使用给定的固定调用签名,那么您可以对可变参数通用lambda执行相同的操作。
如果你不能,你将需要某种形式的异构容器,如:
std::vector<boost::any>
boost::fusion::vector
有关异构容器的示例,请参阅http://en.cppreference.com/w/cpp/language/lambda。
有关lambdas的更多常规信息以及有关生成的成员以及如何在lambda中使用参数的详细信息,请参阅:
#include <iostream>
namespace {
auto out_ = [] ( const auto & val_)
{
std::cout << val_;
return out_ ;
};
auto print = [](auto first_param, auto... params)
{
out_(first_param);
// if there are more params
if constexpr (sizeof...(params) > 0) {
// recurse
print(params...);
}
return print;
};
}
int main()
{
print("Hello ")("from ")("GCC ")(__VERSION__)(" !");
}
考虑一下
wandbox here
(qazxswpoi)这个“打印”lambda是:
看不到任何模板。 (就在下面:))没有看起来像无线电噪音的C ++代码。简单,干净,最重要的是:
难怪“感觉就像一种新语言”。