Lambda表达式作为C ++中的类模板参数14

时间:2014-10-02 19:27:50

标签: c++ templates lambda language-lawyer c++14

问题Lambda expressions as class template parameters询问使用lambda表达式作为类模板参数的可能性。

问题的答案是否定的。但是,它是关于C ++ 11的。

新标准C ++ 14中的情况是否发生了变化?

2 个答案:

答案 0 :(得分:2)

没有C ++ 14中的情况根本没有改变,实际上5.1.2 Lambda表达式 2 中的语言已经收紧:

  

lambda表达式不应出现在未评估的操作数中(Clause   5)。

为:

  

[...] lambda表达式不应出现在未评估的操作数中   (第5条),在模板参数中,在别名声明中,在   typedef声明,或在函数或函数的声明中   模板在其函数体和默认参数之外。 [注意:   意图是防止lambda出现在签名中。 -结束   注意] [...]

Defect report 1607. Lambdas in template parameters导致这种变化。

缺陷报告只是倾向于处理不允许这样做的理由,但我们可以找到一个非常详细的解释,说明为什么在Rationale for lambda-expressions not being allowed in unevaluated contexts中不允许这样做。原因归结为:

  • Lambda表达式没有唯一类型
  • 编译器实现问题:
    • 例如SFINAE
    • 的非凡扩展
    • 可能需要命名一个lambda的整个身体。

鉴于此限制的理由,似乎不太可能改变。

答案 1 :(得分:1)

  

新标准C ++ 14中的情况是否发生了变化?

Lambda表达式仍然不会出现在未评估的操作数中 - 与Xeo's Post中的表达式相同的引用也存在于最新公开的N3797草案中,位于完全相同的位置。

但是,每个闭包类型都有一个删除的默认构造函数(N3797,§5.1.2/ 20):

  

lambda-expression 关联的闭包类型已删除   (8.4.3)默认构造函数和删除的复制赋值运算符。

因此,对于portabiliby和标准一致性(可能是代码在合理的编译器上工作),您需要将一个闭包对象传递给要复制的实例化类的构造函数。但要传递与该专业化的模板参数相同类型的闭包 ,您必须首先定义它:

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的单个实例。其他“闭包类型作为模板参数”方案也会出现类似问题。