如何将lambda的operator()声明为noreturn?

时间:2014-11-12 14:01:42

标签: c++ c++11 lambda attributes noreturn

如何将lambda的operator()声明为noreturn

Ideone接受以下代码:

#include <cstdlib>  
int main() {
    []() [[noreturn]] { std::exit(1); }();
    return 0;
}

Clang 3.5拒绝它:

error: 'noreturn' attribute cannot be applied to types

你可以在godbolt中尝试:http://goo.gl/vsuCsF

哪一个是对的?

更新:相关的标准部分似乎是5.1.2.5,7.6.3,7.6.4,但在阅读之后,我仍然不是100%明确的(i)什么是正确的行为,(ii)如何将lambda的operator()标记为noreturn

3 个答案:

答案 0 :(得分:23)

Clang是对的。属性可以属于声明的函数或其类型;两者是不同的。 [[noreturn]]必须与函数本身相关。

中可以看到差异
// [[noreturn]] appertains to the entity that's being declared
void f [[noreturn]] ();    // §8.3 [dcl.meaning]/p1:
                           // The optional attribute-specifier-seq following a
                           // declarator-id appertains to the entity that is declared."
[[noreturn]] void h ();    // §7 [dcl.dcl]/p2:
                           // "The attribute-specifier-seq in a simple-declaration 
                           // appertains to each of the entities declared by
                           // the declarators of the init-declarator-list."

// ill-formed - [[noreturn]] appertains to the type (§8.3.5 [dcl.fct]/p1: 
// "The optional attribute-specifier-seq appertains to the function type.")
void g () [[noreturn]] {}

的确如果你用g ++编译它会告诉你

warning: attribute ignored [-Wattributes]
 void g () [[noreturn]] {}
                      ^
note: an attribute that appertains to a type-specifier is ignored

请注意,它不会发出g()确实返回的警告。

由于 lambda-declarator 中的“ attribute-specifier-seq 属于相应函数调用运算符或运算符模板的类型”(§5.1.2[ expr.prim.lambda] / p5)而不是那个运算符/运算符模板本身,你不能在那里使用[[noreturn]]。更一般地说,该语言无法将属性应用于lambda本身的operator ()

答案 1 :(得分:4)

因此,lambda delcarator具有以下语法:草案C ++标准部分5.1.2 Lambda表达式

( parameter-declaration-clause ) mutableopt exception-specificationopt attribute-specifier-seqopt trailing-return-typeopt

并且noreturn属性确实是一个有效的 attribute-specifier-seq 所以从语法的角度来看,我没有看到7.6.3 Noreturn属性中的限制>它说(强调我的前进):

  

[...]该属性可以应用于函数中的declarator-id   声明。[...]

似乎并不禁止使用,但确实表明不允许使用。如果我们查看部分7.6.4 承载依赖关系属性,则说:

  

[...]该属性可以应用于a的declarator-id   函数声明或lambda [...]

中的参数声明

明确包含lamda案例的事实强烈表明,7.6.3部分意在排除lambdas,因此clang是正确的。作为旁注,Visual Studio也拒绝此代码。

答案 2 :(得分:3)

  

[C++11: 7.6.3/1]: attribute-token noreturn指定函数不返回。它应该在每个属性列表中最多出现一次,并且不存在 attribute-argument-clause 该属性可以应用于函数声明中的 declarator-id 如果该函数的任何声明,则函数的第一个声明应指定noreturn属性。指定noreturn属性。如果在一个翻译单元中使用noreturn属性声明了一个函数,并且在另一个翻译单元中声明了相同的函数而没有noreturn属性,则该程序格式错误;无需诊断。

我承认,这个措辞并没有禁止该属性出现在其他地方,但是在标准中看不到任何证据的情况下,我并不认为这是为了工作与lambda声明。

因此,Clang是正确的。

它可能会或可能不会告诉there was a patch proposal to Clang to allow GCC-style noreturn attributes on lambdas,但不是标准表格。

很遗憾,此功能未包含在GCC's list of extensions中,因此我无法确切了解此处发生了什么。