Declarations - cppreference.com

##### cppreference.com

##### Search

Create account

##### Namespaces

- Page
- Discussion

##### Variants

##### Views

- View
- Edit
- History

##### Actions

# Declarations

From cppreference.com
< cpp‎ | language

Declarations introduce (or re-introduce) names into the C++ program. Each kind of entity is declared differently. Definitions are declarations that are sufficient to use the entity identified by the name.

A declaration is one of the following:

- Function declaration
- Template declaration
- Explicit template instantiation
- Explicit template specialization
- Namespace definition
- Linkage specification
- Attribute declaration (attr `;`) (since C++11)
- Empty declaration (`;`)
- Block declaration (a declaration that can appear inside a block), which, in turn, can be one of the following:

  - asm definition
  - type alias declaration
  - namespace alias definition
  - using declaration
  - using directive
  - static_assert declaration
  - opaque enum declaration
  - simple declaration

Simple declaration is a statement that introduces, creates, and optionally initializes one or several identifiers, typically variables.

attr(optional) decl-specifier-seq(optional) init-declarator-list(optional) `;` | (1) |

attr(C++11) | - | optional sequence of any number of attributes
decl-specifier-seq | - | sequence of type specifiers including the type name. It is only optional in the declarations of constructors, destructors, and user-defined type conversion functions
init-declarator-list | - | comma-separated list of declarators with optional initializers. Init-declarator-list is optional when declaring a named class/struct/union or a named enumeration

### [edit] Specifiers

decl-specifier-seq is a sequence of the following whitespace-separated specifiers:

- typedef specifier. If present, the entire declaration is a typedef declaration and each declarator introduces a new type name, not an object or a function.
- function specifier (inline, virtual, explicit), only allowed in function declarations
- friend specifier, allowed in class and function declarations.
- constexpr specifier, only allowed in variable definitions, function and function template declarations, and the declaration of static data members of literal type.
- storage class specifier (register, static, thread_local (since C++11), extern, mutable). Only one storage class specifier is allowed, except that `thread_local` may appear together with `extern` or `static`.
- type-specifier-seq, i.e. a sequence of type specifiers, which can be any one of the following:

  - class specifier
  - enum specifier
  - simple type specifier
    - any keyword that names a fundamental type: char, char16_t, char32_t (since C++11), wchar_t, bool, short, int, long, signed, unsigned, float, double, void

auto decltype specifier | (since C++11)

    - previously declared class name (optionally qualified)
    - previously declared enum name (optionally qualified)
    - previously declared typedef-name or type alias (since C++11) (optionally qualified)
    - template name with template arguments (optionally qualified, optionally using template disambiguator)
  - elaborated type specifier
    - the keyword class, struct, or union, followed by the identifier (optionally qualified), previously defined as the name of a class, struct, or union.
    - the keyword class, struct, or union, followed by template name with template arguments (optionally qualified, optionally using template disambiguator), previously defined as the name of a class template.
    - the keyword enum followed by the identifier (optionally qualified), previously declared as the name of an enumeration.
  - typename specifier
  - cv qualifier
  only one type specifier is allowed in a decl-specifier-seq, with the following exceptions:
  - `const` can be combined with any type specifier except itself.
  - `volatile` can be combined with any type specifier except itself.
  - `signed` or `unsigned` can be combined with `char`, `long`, `short`, or `int`.
  - `short` or `long` can be combined with `int`.
  - `long` can be combined with `double`.

- `long` can be combined with `long`. | (since C++11)

Attributes may appear in decl-specifier-seq, in which case they apply to the type determined by the preceding specifiers.

The only specifier that is allowed to appear twice in a decl-specifier-seq is `long` (which can appear twice in a row. All other repeats, such as `const static const`, or `virtual inline virtual` are errors. | (since C++17)

### [edit] Declarators

init-declarator-seq is a comma-separated sequence of one or more init-declarators, which have the following syntax:

declarator initializer(optional) | (1) |

declarator | - | the declarator
initializer | - | optional initializer (except where required, such as when initializing references or const objects). See Initialization for details.

Each init-declaractor in a init-declarator sequence S D1, D2, D3; is processed as if it were a standalone declaration with the same specifiers: S D1; S D2; S D3;.

Each declarator introduces exactly one object, function, or (for typedef declarations) type alias, whose type is provided by decl-specifier-seq and optionally modified by operators such as & (reference to) or [] (array of) or () (function returning) in the declarator. These operators can be applied recursively, as shown below.

A declarator is one of the following:

name attr(optional) | (1) |
qualified-id attr(optional) | (2) |
`...` identifier attr(optional) | (3) | (since C++11)
`*` attr(optional) cv(optional) declarator | (4) |
nested-name-specifier `*` attr(optional) cv(optional) declarator | (5) |
`&` attr(optional) declarator | (6) |
`&&` attr(optional) declarator | (7) | (since C++11)
noptr-declarator `[` constexpr(optional) `]` attr(optional) | (8) |
noptr-declarator `(` parameter-list `)` cv(optional) ref(optional) except(optional) attr(optional) | (9) |

1) The name that is declared. A declarator that consist of just a name, declares an entity of exactly the type provided by decl-specifier-seq.
2) A previously declared name can be re-declared in a different scope.
3) Parameter pack, only appears in function parameter lists for variadic function templates.
4) Pointer declarator: the declaration S * D; declares `D` as a pointer to the type determined by decl-specifier-seq `S`.
5) Pointer to member declaration: the declaration S C::* D; declares `D` as a pointer to member of `C` of type determined by decl-specifier-seq `S`. nested-name-specifier is a sequence of names and scope resolution operators `::`
6) Lvalue reference declarator: the declaration S & D; declares the object `D` with type lvalue reference to the type determined by decl-specifier-seq `S`.
7) Rvalue reference declarator: the declaration S && D; declares the object `D` with type rvalue reference to the type determined by decl-specifier-seq `S`.
8) Array declarator. noptr-declarator any valid declarator, but if it begins with *, &, or &&, it has to be surrounded by parentheses.
9) Function declarator. noptr-declarator any valid declarator, but if it begins with *, &, or &&, it has to be surrounded by parentheses. Note that the outermost function declarator may end with the optional trailing return type.

In all cases, attr is an optional sequence of attributes. When appearing immediately after the identifier, it applies to the object being declared.

cv is a sequence of const and volatile qualifiers, where either qualifier may appear at most once in the sequence.

| This section is incomplete Reason: explain declaration name hiding rules; how a variable/function declaration hides a class (but not a typedef) with the same name

### [edit] Notes

When a block declaration appears inside a block, and an identifier introduced by a declaration was previously declared in an outer block, the outer declaration is hidden for the remainder of the block.

If a declaration introduces a variable with automatic storage duration, it is initialized when its declaration statement is executed. All automatic variables declared in a block are destroyed on exit from the block (regardless how the block is exited: via exception, goto, or by reaching its end), in order opposite to their order of initialization.

### [edit] Examples

Run this code

    class C {
        std::string member; // decl-specifier-seq is "std::string"
                            // declarator is "member"
    } obj, *pObj(&obj);
    // decl-specifier-seq is "class C { std::string member; }"
    // declarator "obj" defines an object of type C
    // declarator "*pObj(&obj)" declares and initializes a pointer to C

    int a = 1, *p = NULL, f(), (*pf)(double);
    // decl-specifier-seq is int
    // declarator a=1 defines and initializes a variable of type int
    // declarator *p=NULL defines and initializes a variable of type int*
    // declarator (f)() declares (but doesn't define)
    //                  a function taking no arguments and returning int
    // declarator (*pf)(double) defines a pointer to function
    //                  taking double and returning int

    int (*(*foo)(double))[3] = NULL;
    // decl-specifier-seq is int
    // 1. declarator "(*(*foo)(double))[3]" is an array declarator:
    //    the type declared is "/nested declarator/ array of 3 int"
    // 2. the nested declarator is "*(*foo)(double))", which is a pointer declarator
    //    the type declared is "/nested declarator/ pointer to array of 3 int"
    // 3. the nested declarator is "(*foo)(double)", which is a function declarator
    //    the type declared is "/nested declarator/ function taking double and returning
    //        pointer to array of 3 int"
    // 4. the nested declarator is "(*foo)" which is a (parenthesized, as required by
    //        function declarator syntax) pointer declarator.
    //    the type declared is "/nested declarator/ pointer to function taking double
    //        and returning pointer to array of 3 int"
    // 5. the nested declarator is "foo", which is an identifier.
    // The declaration declares the object foo of type "pointer to function taking double
    //     and returning pointer to array of 3 int"
    // The initializer "= NULL" provides the initial value of this pointer.

Retrieved from "http://en.cppreference.com/mwiki/index.php?title=cpp/language/declarations&oldid=78013"
Category:

- Todo with reason