c++attributeslanguage-lawyerc++17template-function

How does C++1z standard define the correct location of attributes in a template function declaration?


I noticed that the section 18.8/1 in C++11 and C++14 standards contained the following declaration in the <exception> header synopsis:

[[noreturn]] template <class T> void throw_with_nested(T&& t);

while in the latest C++17 draft the same declaration appears as

template <class T> [[noreturn]] void throw_with_nested(T&& t);

Does this mean that the syntax for the attributes has changed in C++17 or just that the former line was a mistake that got corrected? I can't find any clear description of where the attributes are supposed to appear for function templates, neither in 7.6 nor in 14.5.6. Could someone please point to where is this defined?

Practically speaking, MSVC is happy with both the first and the second declaration, while g++ and clang refuse to compile the first version (the latter with the quite explicit error: an attribute list cannot appear here), so the second version needs to be used anyhow. But I'd like to know whether the first one is, or was, supposed to be valid too or not.


Solution

  • This:

    template <class T> [[noreturn]] void throw_with_nested(T&& t);
    

    was always the only correct option. Grammatically, the productions are, from various sections of [gram]:

    template-declaration:
        template < template-parameter-list > declaration

    declaration:
        [...]
        function-definition
        [...]

    function-definition:
        attribute-specifier-seqopt decl-specifier-seqopt declarator virt-specifier-seqopt function-body

    The attributes have to go after the template <...> introducer.


    It was just a drafting issue in the standard, as submitted by our very own Mr. Wakely.