从C ++ 14开始,我们可以使用泛型lambdas:
auto generic_lambda = [] (auto param) {};
这基本上意味着它的调用操作符基于标记为auto的参数进行模板化。
问题是如何创建一个可以接受可变参数数量的lambda,类似于可变参数函数模板的工作方式?如果这不可能,最接近的东西可以用同样的方法吗?
你会怎么存储它?可以在std::function
吗?
答案 0 :(得分:38)
我不确定你的意图是什么,但不是将它存储在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"));
答案 1 :(得分:29)
如何创建可变参数通用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
有关异类容器的示例,请参阅this question。
有关lambda的更多一般信息以及有关生成的成员以及如何在lambda中使用参数的详细信息,请参阅:
答案 2 :(得分:2)
考虑一下
public class tab1report extends Fragment {
Callback callback;
public interface Callback {
void call();
}
onAttach(Context context) {
callback = (Callback) context;
}
onStart() {
// Some code here
callback.call();
}
}
public class tab1Background extends Activity implements tab1report.Callback {
ListView lv;
lv = (ListView) findViewById(R.id.lv);
//some code here
public void getdata() {
//some code here
}
public void call() {
getdate();
}
}
(wandbox here)这&#34; print&#34; lambda是:
看不到任何模板。 (就在下面:))没有看起来像无线电噪音的C ++代码。简单,干净,最重要的是:
难怪&#34;感觉就像一种新语言&#34;。