C++ 如何创建可变参数泛型 lambda?
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/25885893/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
How to create a variadic generic lambda?
提问by Drax
Since C++14 we can use generic lambdas:
从 C++14 开始,我们可以使用泛型 lambda 表达式:
auto generic_lambda = [] (auto param) {};
This basically means that its call operator is templated based on the parameters marked as auto.
这基本上意味着它的调用运算符是基于标记为 auto 的参数模板化的。
The question is how to create a lambda that can accept a variadic number of parameters similarly to how a variadic function template would work ? If this is not possible what is the closest thing that could be used the same way ?
How would you store it ? Is it possible in a std::function
?
问题是如何创建一个可以接受可变参数数量的 lambda,类似于可变参数函数模板的工作方式?如果这是不可能的,那么可以以相同方式使用的最接近的东西是什么?你会如何储存它?有可能std::function
吗?
采纳答案by Drax
Syntax
句法
How do you create a variadic generic lambda ?
您如何创建可变参数泛型 lambda ?
You can create a variadic generic lambda with the following syntax:
您可以使用以下语法创建可变参数泛型 lambda:
auto variadic_generic_lambda = [] (auto... param) {};
Basically you just add ...
between auto
(possibly ref qualified) and your parameter pack name.
基本上,您只需...
在auto
(可能是 ref 限定的)和您的参数包名称之间添加。
So typically using universal references would give:
所以通常使用通用引用会给出:
auto variadic_generic_lambda = [] (auto&&... param) {};
Usage
用法
How do you use the parameters ?
你如何使用参数?
You should consider the variadic generic parameter as having a template parameter pack type, because it is the case. This more or less implies that most if not all usage of those parameters will require templates one way or the other.
您应该将可变参数泛型参数视为具有模板参数包类型,因为情况就是如此。这或多或少意味着这些参数的大多数(如果不是全部)使用将以一种或另一种方式需要模板。
Here is a typical example:
下面是一个典型的例子:
#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);
}
Storage
贮存
How do you store a variadic generic lambda ?
您如何存储可变参数泛型 lambda ?
You can either use auto
to store a lambda in a variable of its own type, or you can store it in a std::function
but you will only be able to call it with the fixed signature you gave to that std::function
:
您可以使用auto
将 lambda 存储在其自己类型的变量中,也可以将其存储在 a 中,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
What about collections of variadic generic lambdas ?
可变参数泛型 lambda 的集合怎么样?
Since every lambda has a different type you cannot store their direct type in the usual homogeneous containers of the STL. The way it is done with non generic lambdas is to store them in a corresponding std::function
which will have a fixed signature call and that won't restrain anything since your lambda is not generic in the first place and can only be invoked that way:
由于每个 lambda 都有不同的类型,因此您不能将它们的直接类型存储在 STL 的通常同构容器中。使用非泛型 lambda 完成的方式是将它们存储在一个相应的中std::function
,它具有固定的签名调用,并且不会限制任何东西,因为您的 lambda 一开始就不是泛型的,只能以这种方式调用:
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);
As explained in the first part of this storagesection if you can restrain yourself to a given fixed call signature then you can do the same with variadic generic lambdas.
如本存储部分的第一部分所述,如果您可以将自己限制在给定的固定调用签名,那么您可以对可变参数泛型 lambda 执行相同的操作。
If you can't you will need some form of heterogenous container like:
如果你不能,你将需要某种形式的异构容器,如:
std::vector<boost::variant>
std::vector<boost::any>
boost::fusion::vector
std::vector<boost::variant>
std::vector<boost::any>
boost::fusion::vector
See this questionfor an example of heterogenous container.
有关异构容器的示例,请参阅此问题。
What else ?
还有什么 ?
For more general informations on lambdas and for details on the members generated and how to use the parameters within the lambda see:
有关 lambda 的更多一般信息以及有关生成的成员以及如何在 lambda 中使用参数的详细信息,请参阅:
回答by mkaes
I am not sure what your intention is but instead of storing it in a std::function
you can use the lambda itself to capture the params.
This is an example discussed on the boost mailing list. It is used in the boost::hanaimplementation
我不确定您的意图是什么,但std::function
您可以使用 lambda 本身来捕获参数,而不是将其存储在 a 中。这是 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"));
回答by Drax
Consider this
考虑这个
#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) This "print" lambda is:
- Variadic
- Recursive
- Generic
- Fast
- 可变参数
- 递归
- 通用的
- 快速地
And no templates in sight. (just underneath :) ) No C++ code that looks like radio noise. Simple, clean and most importantly:
并且看不到模板。(就在下面:) )没有看起来像无线电噪音的 C++ 代码。简单,干净,最重要的是:
- Easy to maintain
- 易于维护
No wonder "it feels like a new language".
难怪“感觉就像一门新语言”。