9 Declarations [dcl.dcl]

9.3 Declarators [dcl.decl]

9.3.1 General [dcl.decl.general]

A declarator declares a single variable, function, or type, within a declaration.
The init-declarator-list appearing in a declaration is a comma-separated sequence of declarators, each of which can have an initializer.
The three components of a simple-declaration are the attributes ([dcl.attr]), the specifiers (decl-specifier-seq; [dcl.spec]) and the declarators (init-declarator-list).
The specifiers indicate the type, storage class or other properties of the entities being declared.
The declarators specify the names of these entities and (optionally) modify the type of the specifiers with operators such as * (pointer to) and () (function returning).
Initial values can also be specified in a declarator; initializers are discussed in [dcl.init] and [class.init].
Each init-declarator in a declaration is analyzed separately as if it was in a declaration by itself.
[Note 1:
A declaration with several declarators is usually equivalent to the corresponding sequence of declarations each with a single declarator.
That is T D1, D2, ... Dn; is usually equivalent to T D1; T D2; ... T Dn; where T is a decl-specifier-seq and each Di is an init-declarator.
One exception is when a name introduced by one of the declarators hides a type name used by the decl-specifiers, so that when the same decl-specifiers are used in a subsequent declaration, they do not have the same meaning, as in struct S { /* ... */ }; S S, T; // declare two instances of struct S which is not equivalent to struct S { /* ... */ }; S S; S T; // error
Another exception is when T is auto ([dcl.spec.auto]), for example: auto i = 1, j = 2.0; // error: deduced types for i and j do not match as opposed to auto i = 1; // OK: i deduced to have type int auto j = 2.0; // OK: j deduced to have type double
— end note]
The optional requires-clause ([temp.pre]) in an init-declarator or member-declarator shall be present only if the declarator declares a templated function ([dcl.fct]).
When present after a declarator, the requires-clause is called the trailing requires-clause.
The trailing requires-clause introduces the constraint-expression that results from interpreting its constraint-logical-or-expression as a constraint-expression.
[Example 1: void f1(int a) requires true; // error: non-templated function template<typename T> auto f2(T a) -> bool requires true; // OK template<typename T> auto f3(T a) requires true -> bool; // error: requires-clause precedes trailing-return-type void (*pf)() requires true; // error: constraint on a variable void g(int (*)() requires true); // error: constraint on a parameter-declaration auto* p = new void(*)(char) requires true; // error: not a function declaration — end example]