How to declare a lambda's operator() as noreturn?

前端 未结 3 875
野趣味
野趣味 2021-01-17 08:51

How can the operator() of a lambda be declared as noreturn ?

Ideone accepts the following code:

#include   
         


        
相关标签:
3条回答
  • 2021-01-17 09:14

    Clang is correct. An attribute can appertain to a function being declared, or to its type; the two are different. [[noreturn]] must appertain to the function itself. The difference can be seen in

    // [[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]] {}
    

    Indeed if you compile this in g++ it tells you that

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

    Note that it doesn't emit a warning that g() actually does return.

    Since an "attribute-specifier-seq in the lambda-declarator appertains to the type of the corresponding function call operator or operator template" (§5.1.2 [expr.prim.lambda]/p5) rather than to that operator/operator template itself, you can't use [[noreturn]] there. More generally, the language provides no way for you to apply an attribute to the operator () of a lambda itself.

    0 讨论(0)
  • 2021-01-17 09:17

    So a lambda delcarator has the following grammar the draft C++ standard section 5.1.2 Lambda expressions:

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

    and the noreturn attribute is indeed a valid attribute-specifier-seq so from a grammar perspective I don't see a restriction from section 7.6.3 Noreturn attribute it says (emphasis mine going forward):

    [...]The attribute may be applied to the declarator-id in a function declaration.[...]

    which does not seem to forbid your use but it does suggest that it is not allowed. If we look at section 7.6.4 Carries dependency attribute it says:

    [...]The attribute may be applied to the declarator-id of a parameter-declaration in a function declaration or lambda[...]

    the fact that it explicitly includes the lamda case strongly indicates that section 7.6.3 is meant to exclude lambdas and therefore clang would be correct. As a side note Visual Studio also rejects this code.

    0 讨论(0)
  • 2021-01-17 09:21

    [C++11: 7.6.3/1]: The attribute-token noreturn specifies that a function does not return. It shall appear at most once in each attribute-list and no attribute-argument-clause shall be present. The attribute may be applied to the declarator-id in a function declaration. The first declaration of a function shall specify the noreturn attribute if any declaration of that function specifies the noreturn attribute. If a function is declared with the noreturn attribute in one translation unit and the same function is declared without the noreturn attribute in another translation unit, the program is ill-formed; no diagnostic required.

    I concede that this wording, as is, doesn't prohibit the attribute from appearing elsewhere, but in concert with seeing no evidence anywhere in the standard for it, I don't think this is intended to work with lambda declarations.

    Therefore, Clang would be correct.

    It may or may not be telling that there was a patch proposal to Clang to allow GCC-style noreturn attributes on lambdas, but not the standard form.

    Unfortunately, this feature is not included in GCC's list of extensions, so I can't really see exactly what's going on here.

    0 讨论(0)
提交回复
热议问题