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

6

这个问题Lambda表达式作为类模板参数询问了使用Lambda表达式作为类模板参数的可能性。

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

在新标准C++14中,情况有没有改变?


4
C++14对规则进行了加强,考虑到将它们从未求值的操作数中排除的理由,我认为这种情况不会改变。 - Shafik Yaghmour
鉴于最后的草稿,链接帖子中引用的文本(加重强调)并没有改变。因此我认为,情况并没有改变。 - Niall
1
嗯...答案是肯定的,只是不直接。对于C++14来说,我的回答也是“是的,只是不直接”,有点无意义。 - user743382
2个回答

2
C++14中的情况没有改变,事实上,在第5.1.2节“Lambda表达式”的第2段中,语言已经从以下内容加以强化:“lambda表达式不得出现在未求值操作数(第5条款)中。”变为:“[...] lambda表达式不得出现在未求值操作数(第5条款)、模板参数、别名声明、typedef声明或函数或函数模板的声明之外的默认参数中。[注:意图是防止lambda出现在签名中。—end note][...]”,这一变化是由缺陷报告1607. Lambdas in template parameters引起的。
缺陷报告只间接地涉及不允许这样做的原因,但我们可以在lambda表达式不允许在未求值上下文中使用的原因中找到非常详细的解释。其原因归结为:
  • lambda表达式没有唯一的类型
  • 编译器实现问题:
    • 例如SFINAE的异常扩展
    • 可能需要对整个lambda主体进行命名重整。

考虑到此限制的理由,似乎不太可能改变。


1
在新标准C++14中,情况是否有所改变? Lambda表达式仍不会出现在未评估的操作数中——与Xeo's Post中的引用相同,在最新公开草案N3797中,位置完全相同。 然而,每个闭包类型都有一个已删除的默认构造函数(N3797,§5.1.2/20): "与lambda-expression相关联的闭包类型具有已删除的(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的单个实例。其他“将闭包类型作为模板参数”的情况也存在类似的问题。


@dyp 这不是问题所在。 - Columbo
1
9.3.1 非静态成员函数 [class.mfct.non-static] p2:“如果调用类X的非静态成员函数的对象不是类型X或派生自X的类型,则行为未定义。”(我想你可以争辩说措辞有缺陷,因为通过空指针调用意味着该函数没有在任何对象上调用,因此没有在类型不同于X的对象上调用,但是人们普遍认为非静态成员函数需要一个实例。) - user743382
1
@ShafikYaghmour 支持的扩展和编译器未检测到未检测行为的程序之间有区别。__builtin_constant_p 的这种特定用法是支持的扩展的一个很好的例子,如果您不介意您的代码只能在GCC和clang上使用,那么可以使用它。至于“如Richard Smith所建议”的部分,对我来说并不清楚它是否表示他推荐了它,还是仅仅是他提出了这个想法。如果他推荐它,那么我没有任何反对任何人用clang的这个技巧的异议。 :) - user743382
1
@dyp 还有315号问题,其中明确说明通过解引用空指针调用静态成员函数是被定义良好的。我们可以从中得出结论,即仅仅解引用空指针是有效的(即使将其绑定到引用可能无效)。 - user743382
1
就像我说的那样,对于解引用空指针是否真正是未定义行为,我并不清楚。我会称之为 (*static_cast<closure_type_ptr>(nullptr)) () 或者 closure_type_ptr()(),但我不确定是否会使用它,因为它至少处于标准和编译器支持的灰色地带。 - dyp
显示剩余11条评论

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接