Files
cppdraft_translate/cppdraft/dcl/pre.md
2025-10-25 03:02:53 +03:00

29 KiB
Raw Blame History

[dcl.pre]

9 Declarations [dcl]

9.1 Preamble [dcl.pre]

1

#

Declarations generally specify how names are to be interpreted.

Declarations have the form

declaration-seq:
declaration declaration-seqopt

declaration:
name-declaration
special-declaration

name-declaration:
block-declaration
nodeclspec-function-declaration
function-definition
friend-type-declaration
template-declaration
deduction-guide
linkage-specification
namespace-definition
empty-declaration
attribute-declaration
module-import-declaration

special-declaration:
explicit-instantiation
explicit-specialization
export-declaration

block-declaration:
simple-declaration
asm-declaration
namespace-alias-definition
using-declaration
using-enum-declaration
using-directive
static_assert-declaration
consteval-block-declaration
alias-declaration
opaque-enum-declaration

nodeclspec-function-declaration:
attribute-specifier-seqopt declarator ;

alias-declaration:
using identifier attribute-specifier-seqopt = defining-type-id ;

sb-identifier:
...opt identifier attribute-specifier-seqopt

sb-identifier-list:
sb-identifier
sb-identifier-list , sb-identifier

structured-binding-declaration:
attribute-specifier-seqopt decl-specifier-seq ref-qualifieropt [ sb-identifier-list ]

simple-declaration:
decl-specifier-seq init-declarator-listopt ;
attribute-specifier-seq decl-specifier-seq init-declarator-list ;
structured-binding-declaration initializer ;

static_assert-message:
unevaluated-string
constant-expression

static_assert-declaration:
static_assert ( constant-expression ) ;
static_assert ( constant-expression , static_assert-message ) ;

consteval-block-declaration:
consteval compound-statement

empty-declaration:
;

attribute-declaration:
attribute-specifier-seq ;

[Note 1:

asm-declarations are described in [dcl.asm], andlinkage-specifications are described in [dcl.link];function-definitions are described in [dcl.fct.def] andtemplate-declarations anddeduction-guides are described in [temp.deduct.guide];namespace-definitions are described in [namespace.def],using-declarations are described in [namespace.udecl] andusing-directives are described in [namespace.udir].

— end note]

2

#

Certain declarations contain one or more scopes ([basic.scope.scope]).

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.

3

#

If a name-declaration matches the syntactic requirements of friend-type-declaration, it is a friend-type-declaration.

4

#

Asimple-declaration ornodeclspec-function-declaration of the form

attribute-specifier-seqopt decl-specifier-seqopt init-declarator-listopt ;

is divided into three parts.

Attributes are described in [dcl.attr].

decl-specifiers, the principal components of a decl-specifier-seq, are described in [dcl.spec].

declarators, the components of aninit-declarator-list, are described in [dcl.decl].

The attribute-specifier-seq appertains to each of the entities declared by the declarators of the init-declarator-list.

[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 (); // OK — end example]

5

#

If a declarator-id is a name, theinit-declarator and (hence) the declaration introduce that name.

[Note 3:

Otherwise, the declarator-id is a qualified-id or names a destructor or its unqualified-id is a template-id and no name is introduced.

— end note]

The defining-type-specifiers ([dcl.type]) in the decl-specifier-seq and the recursive declarator structure describe a type ([dcl.meaning]), which is then associated with the declarator-id.

6

#

In a simple-declaration, the optionalinit-declarator-list can be omitted only when declaring a class ([class.pre]) or enumeration ([dcl.enum]), that is, when the decl-specifier-seq contains either aclass-specifier, an elaborated-type-specifier with a class-key ([class.name]), or anenum-specifier.

In these cases and whenever aclass-specifier or enum-specifier is present in the decl-specifier-seq, the identifiers in these specifiers are also declared (asclass-names, enum-names, orenumerators, depending on the syntax).

In such cases, the decl-specifier-seq shall (re)introduce one or more names into the program.

[Example 2: enum { }; // errortypedef class { }; // error — end example]

7

#

A simple-declaration or a condition with a structured-binding-declaration is called a structured binding declaration ([dcl.struct.bind]).

Each decl-specifier in the decl-specifier-seq shall beconstexpr,constinit,static,thread_local,auto ([dcl.spec.auto]), or a cv-qualifier.

The declaration shall contain at most one sb-identifier whose 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 concept C = true; C auto [x, y] = std::pair{1, 2}; // error: constrained placeholder-type-specifier// not permitted for structured bindings — end example]

The initializer shall be of the form “= assignment-expression”, of the form “{ assignment-expression }”, or of the form “( assignment-expression )”.

If the structured-binding-declaration appears as a condition, the assignment-expression shall be of non-union class type.

Otherwise, the assignment-expression shall be of array or non-union class type.

8

#

If the decl-specifier-seq contains the typedef specifier, the declaration is a typedef declaration and each declarator-id is declared to be a typedef-name ([dcl.typedef]).

[Note 4:

Such a declarator-id is an identifier ([class.conv.fct]).

— end note]

Otherwise, if the type associated with a declarator-id is a function type ([dcl.fct]), the declaration is a function declaration.

Otherwise, if the type associated with a declarator-id is an object or reference type, the declaration is an object declaration.

Otherwise, the program is ill-formed.

[Example 4: int f(), x; // OK, function declaration for f and object declaration for xextern void g(), // OK, function declaration for g y; // error: void is not an object type — end example]

9

#

An object definition causes storage of appropriate size and alignment to be reserved and any appropriate initialization ([dcl.init]) to be done.

10

#

Syntactic components beyond those found in the general form ofsimple-declaration are added to a function declaration to make afunction-definition.

A token sequence starting with { or = is treated as a function-body ([dcl.fct.def.general]) if the type of the declarator-id ([dcl.meaning.general]) is a function type, and is otherwise treated as a brace-or-equal-initializer ([dcl.init.general]).

[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]

11

#

A nodeclspec-function-declaration shall declare a constructor, destructor, or conversion function.

[Note 6:

Because a member function cannot be subject to a non-defining declaration outside of a class definition ([class.mfct]), a nodeclspec-function-declaration can only be used in a template-declaration ([temp.pre]),explicit-instantiation ([temp.explicit]), orexplicit-specialization ([temp.expl.spec]).

— end note]

12

#

If a static_assert-message matches the syntactic requirements of unevaluated-string, it is an unevaluated-string and the text of the static_assert-message is the text of the unevaluated-string.

Otherwise, a static_assert-message shall be an expression M such 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”.

13

#

In a static_assert-declaration, the constant-expression E is 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 0≤i<N,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]).

14

#

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])); // OK, narrowing allowedtemplate 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); // OK f(c); // error on implementations where sizeof(int) > 1: must be int-sized} — end example]

15

#

For a consteval-block-declaration D, the expression E corresponding to D is: [] -> void static consteval compound-statement ()E shall be a constant expression ([expr.const]).

[Note 7:

The evaluation of the expression corresponding to a consteval-block-declaration ([lex.phases]) can produce injected declarations as side effects.

— end note]

[Example 6: struct S;consteval { std::meta::define_aggregate(^^S, {}); // OKtemplatestruct X { }; // error: local templates are not allowedtemplateconcept C = true; // error: local concepts are not allowedreturn; // OK} — end example]

16

#

An empty-declaration has no effect.

17

#

Except where otherwise specified, the meaning of an attribute-declaration is implementation-defined.