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

12 KiB
Raw Blame History

[dcl.meaning.general]

9 Declarations [dcl]

9.3 Declarators [dcl.decl]

9.3.4 Meaning of declarators [dcl.meaning]

9.3.4.1 General [dcl.meaning.general]

1

#

A declarator contains exactly one declarator-id; it names the entity that is declared.

If the unqualified-id occurring in a declarator-id is a template-id, the declarator shall appear in the declaration of atemplate-declaration ([temp.decls]),explicit-specialization ([temp.expl.spec]), orexplicit-instantiation ([temp.explicit]).

[Note 1:

An unqualified-id that is not an identifier is used to declare certain functions ([class.conv.fct], [class.dtor], [over.oper], [over.literal]).

— end note]

The optional attribute-specifier-seq following a declarator-id appertains to the entity that is declared.

2

#

If the declaration is a friend declaration:

otherwise, if the declarator corresponds ([basic.scope.scope]) to any declaration found of a non-template function, all function template declarations are discarded;

+
      [(2.2.1.3)](#2.2.1.3)

each remaining function template is replaced with the specialization chosen by deduction from the friend declaration ([temp.deduct.decl]) or discarded if deduction fails.

  • (2.2.2)

    The declarator shall correspond to one or more declarations found by the lookup; they shall all have the same target scope, and the target scope of the declarator is that scope.

  • (2.3)

    Otherwise, the terminal name of E is not looked up. The declaration's target scope is the innermost enclosing namespace scope; if the declaration is contained by a block scope, the declaration shall correspond to a reachable ([module.reach]) declaration that inhabits the innermost block scope.

3

#

Otherwise:

  • (3.1)

    If the id-expression in the declarator-id of the declarator is a qualified-id Q, let S be its lookup context ([basic.lookup.qual]); the declaration shall inhabit a namespace scope.

  • (3.2)

    Otherwise, let S be the entity associated with the scope inhabited by the declarator.

  • (3.3)

    If the declarator declares an explicit instantiation or a partial or explicit specialization, the declarator does not bind a name. If it declares a class member, the terminal name of the declarator-id is not looked up; otherwise, only those lookup results that are nominable in S are considered when identifying any function template specialization being declared ([temp.deduct.decl]). [Example 1: namespace N {inline namespace O {template void f(T); // #1template void g(T) {}}namespace P {template void f(T*); // #2, more specialized than #1template int g; }using P::f,P::g;}template<> void N::f(int*) {} // OK, #2 is not nominabletemplate void N::g(int); // error: lookup is ambiguous — end example]

  • (3.4)

    Otherwise, the terminal name of the declarator-id is not looked up. If it is a qualified name, the declarator shall correspond to one or more declarations nominable in S; all the declarations shall have the same target scope and the target scope of the declarator is that scope. [Example 2: namespace Q {namespace V {void f(); }void V::f() { /* ... / } // OKvoid V::g() { / ... / } // error: g() is not yet a member of Vnamespace V {void g(); }}namespace R {void Q::V::g() { / ... */ } // error: R doesn't enclose Q} — end example]

  • (3.5)

    If the declaration inhabits a block scope S and declares a function ([dcl.fct]) or uses the extern specifier, the declaration shall not be attached to a named module ([module.unit]); its target scope is the innermost enclosing namespace scope, but the name is bound in S. [Example 3: namespace X {void p() { q(); // error: q not yet declaredextern void q(); // q is a member of namespace Xextern void r(); // r is a member of namespace X}void middle() { q(); // error: q not found}void q() { /* ... / } // definition of X::q}void q() { / ... / } // some other, unrelated qvoid X::r() { / ... */ } // error: r cannot be declared by qualified-id — end example]

4

#

Astatic,thread_local,extern,mutable,friend,inline,virtual,constexpr,consteval,constinit, ortypedef specifier or an explicit-specifier applies directly to each declarator-id in a declaration; the type specified for each declarator-id depends on both the decl-specifier-seq and its declarator.

5

#

Thus, (for each declarator) a declaration has the formT D whereT is of the form attribute-specifier-seqoptdecl-specifier-seq andD is a declarator.

Following is a recursive procedure for determining the type specified for the containeddeclarator-id by such a declaration.

6

#

First, thedecl-specifier-seq determines a type.

In a declarationT D thedecl-specifier-seqT determines the typeT.

[Example 4:

In the declarationint unsigned i; the type specifiersintunsigned determine the type “unsigned int” ([dcl.type.simple]).

— end example]

7

#

In a declarationattribute-specifier-seqoptTD whereD is an unadorned declarator-id, the type of the declared entity is “€.

8

#

In a declarationTD whereD has the form

( D1 )

the type of the containeddeclarator-id is the same as that of the containeddeclarator-id in the declarationT D1

Parentheses do not alter the type of the embeddeddeclarator-id, but they can alter the binding of complex declarators.