Lambda表达式作为C++14中的类模板参数
Lambda expressions as class template parameters in C++14
Lambda表达式作为类模板参数的问题询问了使用Lambda表达式作为类样板参数的可能性。
这个问题的答案是否定的。然而,它是关于C++11的。
新标准C++14中的情况发生了变化吗?
不,C++14中的情况根本没有改变,事实上,5.1.2
Lambda表达式段落2中的语言已经从收紧
lambda表达式不应出现在未赋值的操作数中(子句5) 。
至:
[…]lambda表达式不应出现在未赋值的操作数中(第5条),在模板中,在别名声明中,在typedef声明,或者在函数或函数的声明中模板在其函数体和默认参数之外。[注:目的是防止lambdas出现在签名中--终止注][…]
缺陷报告1607。模板参数中的Lambdas导致了此更改。
缺陷报告只是间接地处理了不允许这样做的理由,但我们可以找到一个非常详细的解释,解释为什么在未评估的上下文中不允许lambda表达式的理由中不允许这样。原因可以归结为:
- Lambda表达式没有唯一类型
- 编译器实现问题:
- 比如
SFINAE
的非凡扩展 - 对lambda的整个主体进行命名的可能要求
- 比如
考虑到这一限制的理由,它似乎不太可能改变。
新标准C++14中的情况发生了变化吗?
Lambda表达式仍然不能出现在未赋值的操作数中——与Xeo的Post中的引号相同的引号也存在于最新公开的草案N3797中,位置完全相同。
然而,每个闭包类型都有一个已删除的默认构造函数(N3797,§5.1.2/20):
与lambda表达式关联的闭包类型已删除(8.4.3)默认构造函数和已删除的副本赋值运算符。
因此,为了实现可移植性和标准一致性(可能还有代码在合理的编译器上工作),您需要将闭包对象传递给实例化类的构造函数以进行复制。但是要传递与该专门化的模板参数类型相同的闭包对象,无论如何都必须首先定义它:
using my_map_type = map<int, int, decltype([] (auto&& lhs, auto&& rhs) {return lhs < rhs*4;})>;
// Assuming the above compiles
my_map_type m( [] (auto&& lhs, auto&& rhs) {return lhs < rhs*4;} );
// Different closure type - compiler error! What do you copy from!?
没有任何合法的方法来创建第一个lambda的闭包类型的单个对象。因此,即使要删除上述规则,也不能创建my_map_type
的单个实例。类似的问题也出现在其他"闭包类型作为模板参数"的场景中。
- 概念中的cv限定符需要表达式参数列表
- 在函数中使用 const int size 参数创建数组会在 Visual Studio 中抛出错误 C++:表达式的计
- 表达式 SFINAE:如何根据类型是否包含具有一个或多个参数的函数来选择模板版本
- 使用自动推导的 lambda 参数作为常量表达式
- 编译器是否强制根据模板参数计算表达式?
- 错误:参数中无效地使用了无效表达式
- 将折叠表达式传递给可变参数模板
- 为什么带有指针子对象的文字类类型的 constexpr 表达式不能是非类型模板参数
- C++: priority_queue:模板参数中的 lambda 表达式
- 容器如何处理 lambda 表达式的参数
- 在C++ Lambda 表达式中,为什么人们更喜欢按值捕获而不是作为参数传递?
- 整体模板参数。错误:在常量表达式中使用'this'
- 我可以std::在fold表达式中转发参数吗
- 折叠表达式模板参数推导/替换失败
- 折叠表达式和参数包:static_assert 内 Args&& 和 Args 之间的区别
- C++:从捕获函数参数的函数返回 lambda 表达式
- 是否可以使用带有模板化参数的特征块表达式作为左值?
- 编译器在传递 const 变量时返回错误:模板参数不是常量表达式
- 如何在C++中将 lambda 表达式作为参数传递
- 导出模板参数表达式的类型