[dcl.pre] (original) (raw)
9 Declarations [dcl]
9.1 Preamble [dcl.pre]
Declarations generally specify how names are to be interpreted.
Declarations have the form
Unless otherwise stated, utterances in[dcl] about components in, of, or contained by a declaration or subcomponent thereof refer only to those components of the declaration that are not nested within scopes nested within the declaration.
Asimple-declaration ornodeclspec-function-declaration of the form
is divided into three parts.
[Note 2:
In the declaration for an entity, attributes appertaining to that entity can appear at the start of the declaration and after thedeclarator-id for that declaration.
— _end note_]
[Example 1: [[noreturn]] void f [[noreturn]] (); — _end example_]
In such cases, the decl-specifier-seq shall (re)introduce one or more names into the program.
[Example 2: enum { }; typedef class { }; — _end example_]
The declaration shall contain at most one sb-identifierwhose identifier is preceded by an ellipsis.
If the declaration contains any such sb-identifier, it shall declare a templated entity ([temp.pre]).
[Example 3: template<class T> concept C = true; C auto [x, y] = std::pair{1, 2}; — _end example_]
Otherwise, if the type associated with a declarator-idis a function type ([dcl.fct]), the declaration is a function declaration.
Otherwise, if the type associated with a declarator-idis an object or reference type, the declaration is an object declaration.
Otherwise, the program is ill-formed.
[Example 4: int f(), x; extern void g(), y; — _end example_]
An object definition causes storage of appropriate size and alignment to be reserved and any appropriate initialization ([dcl.init]) to be done.
Syntactic components beyond those found in the general form ofsimple-declaration are added to a function declaration to make afunction-definition.
[Note 5:
If the declaration acquires a function type through template instantiation, the program is ill-formed; see [temp.spec.general].
The function type of a function definition cannot be specified with a typedef-name ([dcl.fct]).
— _end note_]
A nodeclspec-function-declaration shall declare a constructor, destructor, or conversion function.
Otherwise, a static_assert-message shall be an expression Msuch that
- the expression M.size() is implicitly convertible to the type std::size_t, and
- the expression M.data() is implicitly convertible to the type “pointer to const char”.
In a static_assert-declaration, the constant-expression Eis contextually converted to bool and the converted expression shall be a constant expression ([expr.const]).
If the value of the expression E when so converted is true or the expression is evaluated in the context of a template definition, the declaration has no effect and the static_assert-message is an unevaluated operand ([expr.context]).
Otherwise, the static_assert-declaration fails and
- the program is ill-formed, and
- if the static_assert-message is a constant-expression M,
- M.size() shall be a converted constant expression of type std::size_t and let N denote the value of that expression,
- M.data(), implicitly converted to the type “pointer to const char”, shall be a core constant expression and let D denote the converted expression,
- for each i where ,D[i] shall be an integral constant expression, and
- the text of the static_assert-message is formed by the sequence of N code units, starting at D, of the ordinary literal encoding ([lex.charset]).
Recommended practice: When a static_assert-declaration fails, the resulting diagnostic message should include the text of the static_assert-message, if one is supplied.
[Example 5: static_assert(sizeof(int) == sizeof(void*), "wrong pointer size");static_assert(sizeof(int[2])); template <class T> void f(T t) { if constexpr (sizeof(T) == sizeof(int)) { use(t);} else { static_assert(false, "must be int-sized");} } void g(char c) { f(0); f(c); } — _end example_]
An empty-declaration has no effect.
Except where otherwise specified, the meaning of an attribute-declarationis implementation-defined.