[dcl.decl]

# 9 Declarations [[dcl]](./#dcl)

## 9.3 Declarators [dcl.decl]

### [9.3.1](#general) General [[dcl.decl.general]](dcl.decl.general)

[1](#general-1)

[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/declarations.tex#L2376)

A declarator declares a single variable, function, or type, within a declaration[.](#general-1.sentence-1)

The[*init-declarator-list*](#nt:init-declarator-list "9.3.1 General [dcl.decl.general]") appearing in a [*simple-declaration*](dcl.pre#nt:simple-declaration "9.1 Preamble [dcl.pre]") is a comma-separated sequence of declarators,
each of which can have an initializer[.](#general-1.sentence-2)

[init-declarator-list:](#nt:init-declarator-list "9.3.1 General [dcl.decl.general]")  
[*init-declarator*](#nt:init-declarator "9.3.1 General [dcl.decl.general]")  
[*init-declarator-list*](#nt:init-declarator-list "9.3.1 General [dcl.decl.general]") , [*init-declarator*](#nt:init-declarator "9.3.1 General [dcl.decl.general]")

[init-declarator:](#nt:init-declarator "9.3.1 General [dcl.decl.general]")  
[*declarator*](#nt:declarator "9.3.1 General [dcl.decl.general]") [*initializer*](dcl.init.general#nt:initializer "9.5.1 General [dcl.init.general]")  
[*declarator*](#nt:declarator "9.3.1 General [dcl.decl.general]") [*requires-clause*](temp.pre#nt:requires-clause "13.1 Preamble [temp.pre]")opt [*function-contract-specifier-seq*](dcl.contract.func#nt:function-contract-specifier-seq "9.4.1 General [dcl.contract.func]")opt

[2](#general-2)

[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/declarations.tex#L2396)

In all contexts, a [*declarator*](#nt:declarator "9.3.1 General [dcl.decl.general]") is interpreted as given below[.](#general-2.sentence-1)

Where an [*abstract-declarator*](#nt:abstract-declarator "9.3.2 Type names [dcl.name]") can be used (or omitted)
in place of a [*declarator*](#nt:declarator "9.3.1 General [dcl.decl.general]") ([[dcl.fct]](#dcl.fct "9.3.4.6 Functions"), [[except.pre]](except.pre "14.1 Preamble")),
it is as if a unique identifier were included in
the appropriate place ([[dcl.name]](#dcl.name "9.3.2 Type names"))[.](#general-2.sentence-2)

The preceding specifiers indicate
the type, storage duration, linkage, or other properties
of the entity or entities being declared[.](#general-2.sentence-3)

Each declarator specifies one entity and
(optionally) names it and/or
modifies the type of the specifiers with operators such as* (pointer to) and () (function returning)[.](#general-2.sentence-4)

[*Note [1](#general-note-1)*:

An [*init-declarator*](#nt:init-declarator "9.3.1 General [dcl.decl.general]") can also specify an initializer ([[dcl.init]](dcl.init "9.5 Initializers"))[.](#general-2.sentence-5)

â *end note*]

[3](#general-3)

[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/declarations.tex#L2413)

Each [*init-declarator*](#nt:init-declarator "9.3.1 General [dcl.decl.general]") or [*member-declarator*](class.mem.general#nt:member-declarator "11.4.1 General [class.mem.general]") in a declaration is analyzed separately as if it were in a declaration by itself[.](#general-3.sentence-1)

[*Note [2](#general-note-2)*:

A declaration with several declarators is usually equivalent to the corresponding
sequence of declarations each with a single declarator[.](#general-3.sentence-2)

That is,T D1, D2, ... Dn; is usually equivalent toT D1; T D2; ... T Dn; where T is a [*decl-specifier-seq*](dcl.spec.general#nt:decl-specifier-seq "9.2.1 General [dcl.spec.general]") and each Di is
an [*init-declarator*](#nt:init-declarator "9.3.1 General [dcl.decl.general]") or [*member-declarator*](class.mem.general#nt:member-declarator "11.4.1 General [class.mem.general]")[.](#general-3.sentence-3)

One exception is when a name introduced by one of the[*declarator*](#nt:declarator "9.3.1 General [dcl.decl.general]")*s* hides a type name used by the[*decl-specifier*](dcl.spec.general#nt:decl-specifier "9.2.1 General [dcl.spec.general]")*s*, so that when the same[*decl-specifier*](dcl.spec.general#nt:decl-specifier "9.2.1 General [dcl.spec.general]")*s* are used in a subsequent declaration,
they do not have the same meaning, as instruct S { /* ... */ };
S S, T; // declare two instances of struct S which is not equivalent tostruct S { /* ... */ };
S S;
S T; // error

Another exception is when T is auto ([[dcl.spec.auto]](dcl.spec.auto "9.2.9.7 Placeholder type specifiers")),
for example:auto i = 1, j = 2.0; // error: deduced types for i and j do not match as opposed toauto i = 1; // OK, i deduced to have type intauto j = 2.0; // OK, j deduced to have type double

â *end note*]

[4](#general-4)

[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/declarations.tex#L2456)

The optional [*requires-clause*](temp.pre#nt:requires-clause "13.1 Preamble [temp.pre]") in an[*init-declarator*](#nt:init-declarator "9.3.1 General [dcl.decl.general]") or [*member-declarator*](class.mem.general#nt:member-declarator "11.4.1 General [class.mem.general]") shall be present only if the declarator declares a
templated function ([[temp.pre]](temp.pre "13.1 Preamble"))[.](#general-4.sentence-1)

When present after a declarator, the [*requires-clause*](temp.pre#nt:requires-clause "13.1 Preamble [temp.pre]") is called the [*trailing* ](#def:requires-clause,trailing "9.3.1 General [dcl.decl.general]")*[*requires-clause*](temp.pre#nt:requires-clause "13.1 Preamble [temp.pre]")*[.](#general-4.sentence-2)

The trailing [*requires-clause*](temp.pre#nt:requires-clause "13.1 Preamble [temp.pre]") introduces the[*constraint-expression*](temp.constr.decl#nt:constraint-expression "13.5.3 Constrained declarations [temp.constr.decl]") that results from interpreting
its [*constraint-logical-or-expression*](temp.pre#nt:constraint-logical-or-expression "13.1 Preamble [temp.pre]") as a[*constraint-expression*](temp.constr.decl#nt:constraint-expression "13.5.3 Constrained declarations [temp.constr.decl]")[.](#general-4.sentence-3)

[*Example [1](#general-example-1)*: void f1(int a) requires true; // error: non-templated functiontemplate<typename T>auto f2(T a) -> bool requires true; // OKtemplate<typename T>auto f3(T a) requires true -> bool; // error: [*requires-clause*](temp.pre#nt:requires-clause "13.1 Preamble [temp.pre]") precedes [*trailing-return-type*](#nt:trailing-return-type "9.3.1 General [dcl.decl.general]")void (*pf)() requires true; // error: constraint on a variablevoid g(int (*)() requires true); // error: constraint on a [*parameter-declaration*](#nt:parameter-declaration "9.3.4.6 Functions [dcl.fct]")auto* p = new void(*)(char) requires true; // error: not a function declaration â *end example*]

[5](#general-5)

[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/declarations.tex#L2485)

The optional [*function-contract-specifier-seq*](dcl.contract.func#nt:function-contract-specifier-seq "9.4.1 General [dcl.contract.func]") ([[dcl.contract.func]](dcl.contract.func "9.4.1 General"))
in an [*init-declarator*](#nt:init-declarator "9.3.1 General [dcl.decl.general]") shall be present only if
the [*declarator*](#nt:declarator "9.3.1 General [dcl.decl.general]") declares a function[.](#general-5.sentence-1)

[6](#general-6)

[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/declarations.tex#L2491)

Declarators have the syntax

[declarator:](#nt:declarator "9.3.1 General [dcl.decl.general]")  
[*ptr-declarator*](#nt:ptr-declarator "9.3.1 General [dcl.decl.general]")  
[*noptr-declarator*](#nt:noptr-declarator "9.3.1 General [dcl.decl.general]") [*parameters-and-qualifiers*](#nt:parameters-and-qualifiers "9.3.1 General [dcl.decl.general]") [*trailing-return-type*](#nt:trailing-return-type "9.3.1 General [dcl.decl.general]")

[ptr-declarator:](#nt:ptr-declarator "9.3.1 General [dcl.decl.general]")  
[*noptr-declarator*](#nt:noptr-declarator "9.3.1 General [dcl.decl.general]")  
[*ptr-operator*](#nt:ptr-operator "9.3.1 General [dcl.decl.general]") [*ptr-declarator*](#nt:ptr-declarator "9.3.1 General [dcl.decl.general]")

[noptr-declarator:](#nt:noptr-declarator "9.3.1 General [dcl.decl.general]")  
[*declarator-id*](#nt:declarator-id "9.3.1 General [dcl.decl.general]") [*attribute-specifier-seq*](dcl.attr.grammar#nt:attribute-specifier-seq "9.13.1 Attribute syntax and semantics [dcl.attr.grammar]")opt  
[*noptr-declarator*](#nt:noptr-declarator "9.3.1 General [dcl.decl.general]") [*parameters-and-qualifiers*](#nt:parameters-and-qualifiers "9.3.1 General [dcl.decl.general]")  
[*noptr-declarator*](#nt:noptr-declarator "9.3.1 General [dcl.decl.general]") [ [*constant-expression*](expr.const#nt:constant-expression "7.7 Constant expressions [expr.const]")opt ] [*attribute-specifier-seq*](dcl.attr.grammar#nt:attribute-specifier-seq "9.13.1 Attribute syntax and semantics [dcl.attr.grammar]")opt  
( [*ptr-declarator*](#nt:ptr-declarator "9.3.1 General [dcl.decl.general]") )

[parameters-and-qualifiers:](#nt:parameters-and-qualifiers "9.3.1 General [dcl.decl.general]")  
( [*parameter-declaration-clause*](#nt:parameter-declaration-clause "9.3.4.6 Functions [dcl.fct]") ) [*cv-qualifier-seq*](#nt:cv-qualifier-seq "9.3.1 General [dcl.decl.general]")opt  
 [*ref-qualifier*](#nt:ref-qualifier "9.3.1 General [dcl.decl.general]")opt [*noexcept-specifier*](except.spec#nt:noexcept-specifier "14.5 Exception specifications [except.spec]")opt [*attribute-specifier-seq*](dcl.attr.grammar#nt:attribute-specifier-seq "9.13.1 Attribute syntax and semantics [dcl.attr.grammar]")opt

[trailing-return-type:](#nt:trailing-return-type "9.3.1 General [dcl.decl.general]")  
-> [*type-id*](#nt:type-id "9.3.2 Type names [dcl.name]")

[ptr-operator:](#nt:ptr-operator "9.3.1 General [dcl.decl.general]")  
* [*attribute-specifier-seq*](dcl.attr.grammar#nt:attribute-specifier-seq "9.13.1 Attribute syntax and semantics [dcl.attr.grammar]")opt [*cv-qualifier-seq*](#nt:cv-qualifier-seq "9.3.1 General [dcl.decl.general]")opt  
& [*attribute-specifier-seq*](dcl.attr.grammar#nt:attribute-specifier-seq "9.13.1 Attribute syntax and semantics [dcl.attr.grammar]")opt  
&& [*attribute-specifier-seq*](dcl.attr.grammar#nt:attribute-specifier-seq "9.13.1 Attribute syntax and semantics [dcl.attr.grammar]")opt  
[*nested-name-specifier*](expr.prim.id.qual#nt:nested-name-specifier "7.5.5.3 Qualified names [expr.prim.id.qual]") * [*attribute-specifier-seq*](dcl.attr.grammar#nt:attribute-specifier-seq "9.13.1 Attribute syntax and semantics [dcl.attr.grammar]")opt [*cv-qualifier-seq*](#nt:cv-qualifier-seq "9.3.1 General [dcl.decl.general]")opt

[cv-qualifier-seq:](#nt:cv-qualifier-seq "9.3.1 General [dcl.decl.general]")  
[*cv-qualifier*](#nt:cv-qualifier "9.3.1 General [dcl.decl.general]") [*cv-qualifier-seq*](#nt:cv-qualifier-seq "9.3.1 General [dcl.decl.general]")opt

[cv-qualifier:](#nt:cv-qualifier "9.3.1 General [dcl.decl.general]")  
const  
volatile

[ref-qualifier:](#nt:ref-qualifier "9.3.1 General [dcl.decl.general]")  
&  
&&

[declarator-id:](#nt:declarator-id "9.3.1 General [dcl.decl.general]")  
...opt [*id-expression*](expr.prim.id.general#nt:id-expression "7.5.5.1 General [expr.prim.id.general]")

### [9.3.2](#dcl.name) Type names [[dcl.name]](dcl.name)

[1](#dcl.name-1)

[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/declarations.tex#L2557)

To specify type conversions explicitly,and as an argument ofsizeof,alignof,new,
ortypeid,
the name of a type shall be specified[.](#dcl.name-1.sentence-1)

This can be done with a[*type-id*](#nt:type-id "9.3.2 Type names [dcl.name]") or [*new-type-id*](expr.new#nt:new-type-id "7.6.2.8 New [expr.new]") ([[expr.new]](expr.new "7.6.2.8 New")),
which is syntactically a declaration for a variable or function
of that type that omits the name of the entity[.](#dcl.name-1.sentence-2)

[type-id:](#nt:type-id "9.3.2 Type names [dcl.name]")  
[*type-specifier-seq*](dcl.type.general#nt:type-specifier-seq "9.2.9.1 General [dcl.type.general]") [*abstract-declarator*](#nt:abstract-declarator "9.3.2 Type names [dcl.name]")opt

[defining-type-id:](#nt:defining-type-id "9.3.2 Type names [dcl.name]")  
[*defining-type-specifier-seq*](dcl.type.general#nt:defining-type-specifier-seq "9.2.9.1 General [dcl.type.general]") [*abstract-declarator*](#nt:abstract-declarator "9.3.2 Type names [dcl.name]")opt

[abstract-declarator:](#nt:abstract-declarator "9.3.2 Type names [dcl.name]")  
[*ptr-abstract-declarator*](#nt:ptr-abstract-declarator "9.3.2 Type names [dcl.name]")  
[*noptr-abstract-declarator*](#nt:noptr-abstract-declarator "9.3.2 Type names [dcl.name]")opt [*parameters-and-qualifiers*](#nt:parameters-and-qualifiers "9.3.1 General [dcl.decl.general]") [*trailing-return-type*](#nt:trailing-return-type "9.3.1 General [dcl.decl.general]")  
[*abstract-pack-declarator*](#nt:abstract-pack-declarator "9.3.2 Type names [dcl.name]")

[ptr-abstract-declarator:](#nt:ptr-abstract-declarator "9.3.2 Type names [dcl.name]")  
[*noptr-abstract-declarator*](#nt:noptr-abstract-declarator "9.3.2 Type names [dcl.name]")  
[*ptr-operator*](#nt:ptr-operator "9.3.1 General [dcl.decl.general]") [*ptr-abstract-declarator*](#nt:ptr-abstract-declarator "9.3.2 Type names [dcl.name]")opt

[noptr-abstract-declarator:](#nt:noptr-abstract-declarator "9.3.2 Type names [dcl.name]")  
[*noptr-abstract-declarator*](#nt:noptr-abstract-declarator "9.3.2 Type names [dcl.name]")opt [*parameters-and-qualifiers*](#nt:parameters-and-qualifiers "9.3.1 General [dcl.decl.general]")  
[*noptr-abstract-declarator*](#nt:noptr-abstract-declarator "9.3.2 Type names [dcl.name]")opt [ [*constant-expression*](expr.const#nt:constant-expression "7.7 Constant expressions [expr.const]")opt ] [*attribute-specifier-seq*](dcl.attr.grammar#nt:attribute-specifier-seq "9.13.1 Attribute syntax and semantics [dcl.attr.grammar]")opt  
( [*ptr-abstract-declarator*](#nt:ptr-abstract-declarator "9.3.2 Type names [dcl.name]") )

[abstract-pack-declarator:](#nt:abstract-pack-declarator "9.3.2 Type names [dcl.name]")  
[*noptr-abstract-pack-declarator*](#nt:noptr-abstract-pack-declarator "9.3.2 Type names [dcl.name]")  
[*ptr-operator*](#nt:ptr-operator "9.3.1 General [dcl.decl.general]") [*abstract-pack-declarator*](#nt:abstract-pack-declarator "9.3.2 Type names [dcl.name]")

[noptr-abstract-pack-declarator:](#nt:noptr-abstract-pack-declarator "9.3.2 Type names [dcl.name]")  
[*noptr-abstract-pack-declarator*](#nt:noptr-abstract-pack-declarator "9.3.2 Type names [dcl.name]") [*parameters-and-qualifiers*](#nt:parameters-and-qualifiers "9.3.1 General [dcl.decl.general]")  
...

It is possible to identify uniquely the location in the[*abstract-declarator*](#nt:abstract-declarator "9.3.2 Type names [dcl.name]") where the identifier would appear if the construction were a declarator
in a declaration[.](#dcl.name-1.sentence-3)

The named type is then the same as the type of the
hypothetical identifier[.](#dcl.name-1.sentence-4)

[*Example [1](#dcl.name-example-1)*:

int // int iint * // int *piint *[3] // int *p[3]int (*)[3] // int (*p3i)[3]int *() // int *f()int (*)(double) // int (*pf)(double) name respectively the types
âintâ,
âpointer tointâ,
âarray of 3 pointers tointâ,
âpointer to array of 3intâ,
âfunction of (no parameters) returning pointer tointâ,
and âpointer to a function of
(double)
returningintâ[.](#dcl.name-1.sentence-5)

â *end example*]

[2](#dcl.name-2)

[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/declarations.tex#L2646)

[*Note [1](#dcl.name-note-1)*:

A type can also be named by a [*typedef-name*](dcl.typedef#nt:typedef-name "9.2.4 The typedef specifier [dcl.typedef]"),
which is introduced by a typedef declaration
or [*alias-declaration*](dcl.pre#nt:alias-declaration "9.1 Preamble [dcl.pre]") ([[dcl.typedef]](dcl.typedef "9.2.4 The typedef specifier"))[.](#dcl.name-2.sentence-1)

â *end note*]

### [9.3.3](#dcl.ambig.res) Ambiguity resolution [[dcl.ambig.res]](dcl.ambig.res)

[1](#dcl.ambig.res-1)

[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/declarations.tex#L2657)

The ambiguity arising from the similarity between a function-style cast and
a declaration mentioned in [[stmt.ambig]](stmt.ambig "8.11 Ambiguity resolution") can also occur in the context of a declaration[.](#dcl.ambig.res-1.sentence-1)

In that context, the choice is between
an object declaration
with a function-style cast as the initializer and
a declaration involving a function declarator
with a redundant set of parentheses around a parameter name[.](#dcl.ambig.res-1.sentence-2)

Just as for the ambiguities mentioned in [[stmt.ambig]](stmt.ambig "8.11 Ambiguity resolution"),
the resolution is to consider any construct,
such as the potential parameter declaration,
that could possibly be a declaration
to be a declaration[.](#dcl.ambig.res-1.sentence-3)

However, a construct that can syntactically be a [*declaration*](dcl.pre#nt:declaration "9.1 Preamble [dcl.pre]") whose outermost [*declarator*](#nt:declarator "9.3.1 General [dcl.decl.general]") would match the grammar of a [*declarator*](#nt:declarator "9.3.1 General [dcl.decl.general]") with a [*trailing-return-type*](#nt:trailing-return-type "9.3.1 General [dcl.decl.general]") is a declaration only if it starts with auto[.](#dcl.ambig.res-1.sentence-4)

[*Note [1](#dcl.ambig.res-note-1)*:

A declaration can be explicitly disambiguated by adding parentheses
around the argument[.](#dcl.ambig.res-1.sentence-5)

The ambiguity can be avoided by use of copy-initialization or
list-initialization syntax, or by use of a non-function-style cast[.](#dcl.ambig.res-1.sentence-6)

â *end note*]

[*Example [1](#dcl.ambig.res-example-1)*: struct S { S(int);};typedef struct BB { int C[2]; } *B, C;

void foo(double a) { S v(int(a)); // function declaration S w(int()); // function declaration S x((int(a))); // object declaration S y((int)a); // object declaration S z = int(a); // object declaration S a(B()->C); // object declaration S b(auto()->C); // function declaration} â *end example*]

[2](#dcl.ambig.res-2)

[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/declarations.tex#L2700)

An ambiguity can arise from the similarity between a function-style
cast and a[*type-id*](#nt:type-id "9.3.2 Type names [dcl.name]")[.](#dcl.ambig.res-2.sentence-1)

The resolution is that any construct that could possibly be a[*type-id*](#nt:type-id "9.3.2 Type names [dcl.name]") in its syntactic context shall be considered a[*type-id*](#nt:type-id "9.3.2 Type names [dcl.name]")[.](#dcl.ambig.res-2.sentence-2)

However, a construct that can syntactically be a [*type-id*](#nt:type-id "9.3.2 Type names [dcl.name]") whose outermost [*abstract-declarator*](#nt:abstract-declarator "9.3.2 Type names [dcl.name]") would match the grammar of an [*abstract-declarator*](#nt:abstract-declarator "9.3.2 Type names [dcl.name]") with a [*trailing-return-type*](#nt:trailing-return-type "9.3.1 General [dcl.decl.general]") is considered a [*type-id*](#nt:type-id "9.3.2 Type names [dcl.name]") only if it starts with auto[.](#dcl.ambig.res-2.sentence-3)

[*Example [2](#dcl.ambig.res-example-2)*: template <class T> struct X {};template <int N> struct Y {};
X<int()> a; // type-id X<int(1)> b; // expression (ill-formed) Y<int()> c; // type-id (ill-formed) Y<int(1)> d; // expressionvoid foo(signed char a) {sizeof(int()); // type-id (ill-formed)sizeof(int(a)); // expressionsizeof(int(unsigned(a))); // type-id (ill-formed)(int())+1; // type-id (ill-formed)(int(a))+1; // expression(int(unsigned(a)))+1; // type-id (ill-formed)}typedef struct BB { int C[2]; } *B, C;void g() {sizeof(B()->C[1]); // OK, sizeof(expression)sizeof(auto()->C[1]); // error: sizeof of a function returning an array} â *end example*]

[3](#dcl.ambig.res-3)

[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/declarations.tex#L2740)

Another ambiguity arises in a[*parameter-declaration-clause*](#nt:parameter-declaration-clause "9.3.4.6 Functions [dcl.fct]") when a[*type-name*](dcl.type.simple#nt:type-name "9.2.9.3 Simple type specifiers [dcl.type.simple]") is nested in parentheses[.](#dcl.ambig.res-3.sentence-1)

In this case, the choice is between the declaration of a parameter of type
pointer to function and the declaration of a parameter with redundant
parentheses around the[*declarator-id*](#nt:declarator-id "9.3.1 General [dcl.decl.general]")[.](#dcl.ambig.res-3.sentence-2)

The resolution is to consider the[*type-name*](dcl.type.simple#nt:type-name "9.2.9.3 Simple type specifiers [dcl.type.simple]") as a[*simple-type-specifier*](dcl.type.simple#nt:simple-type-specifier "9.2.9.3 Simple type specifiers [dcl.type.simple]") rather than a[*declarator-id*](#nt:declarator-id "9.3.1 General [dcl.decl.general]")[.](#dcl.ambig.res-3.sentence-3)

[*Example [3](#dcl.ambig.res-example-3)*: class C { };void f(int(C)) { } // void f(int(*fp)(C c)) { }// not: void f(int C) { }int g(C);

void foo() { f(1); // error: cannot convert 1 to function pointer f(g); // OK}

For another example,class C { };void h(int *(C[10])); // void h(int *(*_fp)(C _parm[10]));// not: void h(int *C[10]);

â *end example*]

### [9.3.4](#dcl.meaning) Meaning of declarators [[dcl.meaning]](dcl.meaning)

#### [9.3.4.1](#dcl.meaning.general) General [[dcl.meaning.general]](dcl.meaning.general)

[1](#dcl.meaning.general-1)

[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/declarations.tex#L2782)

A declarator contains exactly one [*declarator-id*](#nt:declarator-id "9.3.1 General [dcl.decl.general]");
it names the entity that is declared[.](#dcl.meaning.general-1.sentence-1)

If the [*unqualified-id*](expr.prim.id.unqual#nt:unqualified-id "7.5.5.2 Unqualified names [expr.prim.id.unqual]") occurring in a [*declarator-id*](#nt:declarator-id "9.3.1 General [dcl.decl.general]") is a [*template-id*](temp.names#nt:template-id "13.3 Names of template specializations [temp.names]"),
the declarator shall appear in the [*declaration*](dcl.pre#nt:declaration "9.1 Preamble [dcl.pre]") of a[*template-declaration*](temp.pre#nt:template-declaration "13.1 Preamble [temp.pre]") ([[temp.decls]](temp.decls "13.7 Template declarations")),[*explicit-specialization*](temp.expl.spec#nt:explicit-specialization "13.9.4 Explicit specialization [temp.expl.spec]") ([[temp.expl.spec]](temp.expl.spec "13.9.4 Explicit specialization")), or[*explicit-instantiation*](temp.explicit#nt:explicit-instantiation "13.9.3 Explicit instantiation [temp.explicit]") ([[temp.explicit]](temp.explicit "13.9.3 Explicit instantiation"))[.](#dcl.meaning.general-1.sentence-2)

[*Note [1](#dcl.meaning.general-note-1)*:

An [*unqualified-id*](expr.prim.id.unqual#nt:unqualified-id "7.5.5.2 Unqualified names [expr.prim.id.unqual]") that is not an [*identifier*](lex.name#nt:identifier "5.11 Identifiers [lex.name]") is used to declare
certain functions ([[class.conv.fct]](class.conv.fct "11.4.8.3 Conversion functions"), [[class.dtor]](class.dtor "11.4.7 Destructors"), [[over.oper]](over.oper "12.4 Overloaded operators"), [[over.literal]](over.literal "12.6 User-defined literals"))[.](#dcl.meaning.general-1.sentence-3)

â *end note*]

The optional [*attribute-specifier-seq*](dcl.attr.grammar#nt:attribute-specifier-seq "9.13.1 Attribute syntax and semantics [dcl.attr.grammar]") following a [*declarator-id*](#nt:declarator-id "9.3.1 General [dcl.decl.general]") appertains to the entity that is declared[.](#dcl.meaning.general-1.sentence-4)

[2](#dcl.meaning.general-2)

[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/declarations.tex#L2799)

If the declaration is a friend declaration:

- [(2.1)](#dcl.meaning.general-2.1)

  The [*declarator*](#nt:declarator "9.3.1 General [dcl.decl.general]") does not bind a name[.](#dcl.meaning.general-2.1.sentence-1)

- [(2.2)](#dcl.meaning.general-2.2)

  If the [*id-expression*](expr.prim.id.general#nt:id-expression "7.5.5.1 General [expr.prim.id.general]") E in
the [*declarator-id*](#nt:declarator-id "9.3.1 General [dcl.decl.general]") of the [*declarator*](#nt:declarator "9.3.1 General [dcl.decl.general]") is
a [*qualified-id*](expr.prim.id.qual#nt:qualified-id "7.5.5.3 Qualified names [expr.prim.id.qual]") or a [*template-id*](temp.names#nt:template-id "13.3 Names of template specializations [temp.names]"):
  * [(2.2.1)](#dcl.meaning.general-2.2.1)

      If the friend declaration is not a template declaration,
then in the lookup for the terminal name of E:
    +
          [(2.2.1.1)](#dcl.meaning.general-2.2.1.1)
if the [*unqualified-id*](expr.prim.id.unqual#nt:unqualified-id "7.5.5.2 Unqualified names [expr.prim.id.unqual]") in E is a [*template-id*](temp.names#nt:template-id "13.3 Names of template specializations [temp.names]"),
all function declarations are discarded;

    +
          [(2.2.1.2)](#dcl.meaning.general-2.2.1.2)
otherwise,
if the [*declarator*](#nt:declarator "9.3.1 General [dcl.decl.general]") corresponds ([[basic.scope.scope]](basic.scope.scope "6.4.1 General")) to
any declaration found of a non-template function,
all function template declarations are discarded;

    +
          [(2.2.1.3)](#dcl.meaning.general-2.2.1.3)
each remaining function template is replaced with the specialization chosen by
deduction from the friend declaration ([[temp.deduct.decl]](temp.deduct.decl "13.10.3.7 Deducing template arguments from a function declaration")) or
discarded if deduction fails[.](#dcl.meaning.general-2.2.1.sentence-1)

  * [(2.2.2)](#dcl.meaning.general-2.2.2)

      The [*declarator*](#nt:declarator "9.3.1 General [dcl.decl.general]") 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*](#nt:declarator "9.3.1 General [dcl.decl.general]") is that scope[.](#dcl.meaning.general-2.2.2.sentence-1)

- [(2.3)](#dcl.meaning.general-2.3)

  Otherwise, the terminal name of E is not looked up[.](#dcl.meaning.general-2.3.sentence-1)
  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]](module.reach "10.7 Reachability")) declaration
that inhabits the innermost block scope[.](#dcl.meaning.general-2.3.sentence-2)

[3](#dcl.meaning.general-3)

[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/declarations.tex#L2840)

Otherwise:

- [(3.1)](#dcl.meaning.general-3.1)

  If the [*id-expression*](expr.prim.id.general#nt:id-expression "7.5.5.1 General [expr.prim.id.general]") in
the [*declarator-id*](#nt:declarator-id "9.3.1 General [dcl.decl.general]") of the [*declarator*](#nt:declarator "9.3.1 General [dcl.decl.general]") is
a [*qualified-id*](expr.prim.id.qual#nt:qualified-id "7.5.5.3 Qualified names [expr.prim.id.qual]") Q,
let S be its lookup context ([[basic.lookup.qual]](basic.lookup.qual "6.5.5 Qualified name lookup"));
the declaration shall inhabit a namespace scope[.](#dcl.meaning.general-3.1.sentence-1)

- [(3.2)](#dcl.meaning.general-3.2)

  Otherwise, let S be the entity associated with the scope inhabited by
the [*declarator*](#nt:declarator "9.3.1 General [dcl.decl.general]")[.](#dcl.meaning.general-3.2.sentence-1)

- [(3.3)](#dcl.meaning.general-3.3)

  If the [*declarator*](#nt:declarator "9.3.1 General [dcl.decl.general]") declares
an explicit instantiation or a partial or explicit specialization,
the [*declarator*](#nt:declarator "9.3.1 General [dcl.decl.general]") does not bind a name[.](#dcl.meaning.general-3.3.sentence-1)
  If it declares a class member,
the terminal name of the [*declarator-id*](#nt:declarator-id "9.3.1 General [dcl.decl.general]") 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]](temp.deduct.decl "13.10.3.7 Deducing template arguments from a function declaration"))[.](#dcl.meaning.general-3.3.sentence-2)
  [*Example [1](#dcl.meaning.general-example-1)*: namespace N {inline namespace O {template<class T> void f(T); // #1template<class T> void g(T) {}}namespace P {template<class T> void f(T*); // #2, more specialized than #1template<class> 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)](#dcl.meaning.general-3.4)

  Otherwise,
the terminal name of the [*declarator-id*](#nt:declarator-id "9.3.1 General [dcl.decl.general]") is not looked up[.](#dcl.meaning.general-3.4.sentence-1)
  If it is a qualified name,
the [*declarator*](#nt:declarator "9.3.1 General [dcl.decl.general]") 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*](#nt:declarator "9.3.1 General [dcl.decl.general]") is that scope[.](#dcl.meaning.general-3.4.sentence-2)
  [*Example [2](#dcl.meaning.general-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)](#dcl.meaning.general-3.5)

  If the declaration inhabits a block scope S and
declares a function ([[dcl.fct]](#dcl.fct "9.3.4.6 Functions")) or uses the extern specifier,
the declaration shall not be attached to a named module ([[module.unit]](module.unit "10.1 Module units and purviews"));
its target scope is the innermost enclosing namespace scope,
but the name is bound in S[.](#dcl.meaning.general-3.5.sentence-1)
  [*Example [3](#dcl.meaning.general-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*](expr.prim.id.qual#nt:qualified-id "7.5.5.3 Qualified names [expr.prim.id.qual]") â *end example*]

[4](#dcl.meaning.general-4)

[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/declarations.tex#L2932)

Astatic,thread_local,extern,mutable,friend,inline,virtual,constexpr,consteval,constinit,
ortypedef specifier
or an [*explicit-specifier*](dcl.fct.spec#nt:explicit-specifier "9.2.3 Function specifiers [dcl.fct.spec]") applies directly to each [*declarator-id*](#nt:declarator-id "9.3.1 General [dcl.decl.general]") in a declaration;
the type specified for each [*declarator-id*](#nt:declarator-id "9.3.1 General [dcl.decl.general]") depends on
both the [*decl-specifier-seq*](dcl.spec.general#nt:decl-specifier-seq "9.2.1 General [dcl.spec.general]") and its [*declarator*](#nt:declarator "9.3.1 General [dcl.decl.general]")[.](#dcl.meaning.general-4.sentence-1)

[5](#dcl.meaning.general-5)

[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/declarations.tex#L2953)

Thus, (for each [*declarator*](#nt:declarator "9.3.1 General [dcl.decl.general]")) a declaration has the formT D whereT is of the form [*attribute-specifier-seq*](dcl.attr.grammar#nt:attribute-specifier-seq "9.13.1 Attribute syntax and semantics [dcl.attr.grammar]")opt[*decl-specifier-seq*](dcl.spec.general#nt:decl-specifier-seq "9.2.1 General [dcl.spec.general]") andD is a declarator[.](#dcl.meaning.general-5.sentence-1)

Following is a recursive procedure for determining
the type specified for the contained[*declarator-id*](#nt:declarator-id "9.3.1 General [dcl.decl.general]") by such a declaration[.](#dcl.meaning.general-5.sentence-2)

[6](#dcl.meaning.general-6)

[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/declarations.tex#L2970)

First, the[*decl-specifier-seq*](dcl.spec.general#nt:decl-specifier-seq "9.2.1 General [dcl.spec.general]") determines a type[.](#dcl.meaning.general-6.sentence-1)

In a declarationT D the[*decl-specifier-seq*](dcl.spec.general#nt:decl-specifier-seq "9.2.1 General [dcl.spec.general]")T determines the typeT[.](#dcl.meaning.general-6.sentence-2)

[*Example [4](#dcl.meaning.general-example-4)*:

In the declarationint unsigned i; the type specifiersintunsigned determine the type
âunsigned intâ ([[dcl.type.simple]](dcl.type.simple "9.2.9.3 Simple type specifiers"))[.](#dcl.meaning.general-6.sentence-3)

â *end example*]

[7](#dcl.meaning.general-7)

[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/declarations.tex#L2995)

In a declaration[*attribute-specifier-seq*](dcl.attr.grammar#nt:attribute-specifier-seq "9.13.1 Attribute syntax and semantics [dcl.attr.grammar]")optTD whereD is an unadorned [*declarator-id*](#nt:declarator-id "9.3.1 General [dcl.decl.general]"),
the type of the declared entity is
âTâ[.](#dcl.meaning.general-7.sentence-1)

[8](#dcl.meaning.general-8)

[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/declarations.tex#L3006)

In a declarationTD whereD has the form

( D1 )

the type of the contained[*declarator-id*](#nt:declarator-id "9.3.1 General [dcl.decl.general]") is the same as that of the contained[*declarator-id*](#nt:declarator-id "9.3.1 General [dcl.decl.general]") in the declarationT D1

Parentheses do not alter the type of the embedded[*declarator-id*](#nt:declarator-id "9.3.1 General [dcl.decl.general]"),
but they can alter the binding of complex declarators[.](#dcl.meaning.general-8.sentence-2)

#### [9.3.4.2](#dcl.ptr) Pointers [[dcl.ptr]](dcl.ptr)

[1](#dcl.ptr-1)

[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/declarations.tex#L3032)

In a declarationTD whereD has the form

* [*attribute-specifier-seq*](dcl.attr.grammar#nt:attribute-specifier-seq "9.13.1 Attribute syntax and semantics [dcl.attr.grammar]")opt [*cv-qualifier-seq*](#nt:cv-qualifier-seq "9.3.1 General [dcl.decl.general]")opt D1

and the type of the contained [*declarator-id*](#nt:declarator-id "9.3.1 General [dcl.decl.general]") in the declarationTD1 is â*derived-declarator-type-list*Tâ,
the type of the [*declarator-id*](#nt:declarator-id "9.3.1 General [dcl.decl.general]") inD is â*derived-declarator-type-list* [*cv-qualifier-seq*](#nt:cv-qualifier-seq "9.3.1 General [dcl.decl.general]") pointer toTâ[.](#dcl.ptr-1.sentence-1)

The[*cv-qualifier*](#nt:cv-qualifier "9.3.1 General [dcl.decl.general]")*s* apply to the pointer and not to the object pointed to[.](#dcl.ptr-1.sentence-2)

Similarly, the optional [*attribute-specifier-seq*](dcl.attr.grammar#nt:attribute-specifier-seq "9.13.1 Attribute syntax and semantics [dcl.attr.grammar]") ([[dcl.attr.grammar]](dcl.attr.grammar "9.13.1 Attribute syntax and semantics")) appertains to the pointer and not to the object pointed to[.](#dcl.ptr-1.sentence-3)

[2](#dcl.ptr-2)

[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/declarations.tex#L3058)

[*Example [1](#dcl.ptr-example-1)*:

The declarationsconst int ci = 10, *pc = &ci, *const cpc = pc, **ppc;int i, *p, *const cp = &i; declareci,
a constant integer;pc,
a pointer to a constant integer;cpc,
a constant pointer to a constant integer;ppc,
a pointer to a pointer to a constant integer;i,
an integer;p,
a pointer to integer; andcp,
a constant pointer to integer[.](#dcl.ptr-2.sentence-1)

The value ofci,cpc,
andcp cannot be changed after initialization[.](#dcl.ptr-2.sentence-2)

The value ofpc can be changed, and so can the object pointed to bycp[.](#dcl.ptr-2.sentence-3)

Examples of
some correct operations arei = ci;*cp = ci;
pc++;
pc = cpc;
pc = p;
ppc = &pc;

Examples of ill-formed operations areci = 1; // error ci++; // error*pc = 2; // error cp = &ci; // error cpc++; // error p = pc; // error ppc = &p; // error

Each is unacceptable because it would either change the value of an object declaredconst or allow it to be changed through a cv-unqualified pointer later, for example:*ppc = &ci; // OK, but would make p point to ci because of previous error*p = 5; // clobber ci

â *end example*]

[3](#dcl.ptr-3)

[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/declarations.tex#L3121)

See also [[expr.assign]](expr.assign "7.6.19 Assignment and compound assignment operators") and [[dcl.init]](dcl.init "9.5 Initializers")[.](#dcl.ptr-3.sentence-1)

[4](#dcl.ptr-4)

[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/declarations.tex#L3124)

[*Note [1](#dcl.ptr-note-1)*:

Forming a pointer to reference type is ill-formed; see [[dcl.ref]](#dcl.ref "9.3.4.3 References")[.](#dcl.ptr-4.sentence-1)

Forming a function pointer type is ill-formed if the function type has[*cv-qualifier*](#nt:cv-qualifier "9.3.1 General [dcl.decl.general]")*s* or a [*ref-qualifier*](#nt:ref-qualifier "9.3.1 General [dcl.decl.general]");
see [[dcl.fct]](#dcl.fct "9.3.4.6 Functions")[.](#dcl.ptr-4.sentence-2)

Since the address of a bit-field ([[class.bit]](class.bit "11.4.10 Bit-fields")) cannot be taken,
a pointer can never point to a bit-field[.](#dcl.ptr-4.sentence-3)

â *end note*]

#### [9.3.4.3](#dcl.ref) References [[dcl.ref]](dcl.ref)

[1](#dcl.ref-1)

[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/declarations.tex#L3137)

In a declarationTD whereD has either of the forms

& [*attribute-specifier-seq*](dcl.attr.grammar#nt:attribute-specifier-seq "9.13.1 Attribute syntax and semantics [dcl.attr.grammar]")opt D1  
&& [*attribute-specifier-seq*](dcl.attr.grammar#nt:attribute-specifier-seq "9.13.1 Attribute syntax and semantics [dcl.attr.grammar]")opt D1

and the type of the contained [*declarator-id*](#nt:declarator-id "9.3.1 General [dcl.decl.general]") in the declarationTD1 is â*derived-declarator-type-list*Tâ,
the type of the [*declarator-id*](#nt:declarator-id "9.3.1 General [dcl.decl.general]") inD is â*derived-declarator-type-list* reference toTâ[.](#dcl.ref-1.sentence-1)

The optional [*attribute-specifier-seq*](dcl.attr.grammar#nt:attribute-specifier-seq "9.13.1 Attribute syntax and semantics [dcl.attr.grammar]") appertains to the reference type[.](#dcl.ref-1.sentence-2)

Cv-qualified references are ill-formed except when the cv-qualifiers
are introduced through the use of a[*typedef-name*](dcl.typedef#nt:typedef-name "9.2.4 The typedef specifier [dcl.typedef]") ([[dcl.typedef]](dcl.typedef "9.2.4 The typedef specifier"), [[temp.param]](temp.param "13.2 Template parameters")) or[*decltype-specifier*](dcl.type.decltype#nt:decltype-specifier "9.2.9.6 Decltype specifiers [dcl.type.decltype]") ([[dcl.type.decltype]](dcl.type.decltype "9.2.9.6 Decltype specifiers")),
in which case the cv-qualifiers are ignored[.](#dcl.ref-1.sentence-3)

[*Example [1](#dcl.ref-example-1)*: typedef int& A;const A aref = 3; // error: lvalue reference to non-const initialized with rvalue

The type ofaref is âlvalue reference to intâ,
not âlvalue reference to const intâ[.](#dcl.ref-1.sentence-4)

â *end example*]

[*Note [1](#dcl.ref-note-1)*:

A reference can be thought of as a name of an object[.](#dcl.ref-1.sentence-5)

â *end note*]

Forming the type
âreference to cv voidâ
is ill-formed[.](#dcl.ref-1.sentence-6)

[2](#dcl.ref-2)

[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/declarations.tex#L3183)

A reference type that is declared using & is called an[*lvalue reference*](#def:lvalue_reference "9.3.4.3 References [dcl.ref]"), and a reference type that
is declared using && is called an[*rvalue reference*](#def:rvalue_reference "9.3.4.3 References [dcl.ref]")[.](#dcl.ref-2.sentence-1)

Lvalue references and
rvalue references are distinct types[.](#dcl.ref-2.sentence-2)

Except where explicitly noted, they are
semantically equivalent and commonly referred to as references[.](#dcl.ref-2.sentence-3)

[3](#dcl.ref-3)

[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/declarations.tex#L3191)

[*Example [2](#dcl.ref-example-2)*:

void f(double& a) { a += 3.14; }// ...double d = 0;
f(d); declaresa to be a reference parameter off so the callf(d) will add3.14 tod[.](#dcl.ref-3.sentence-1)

int v[20];// ...int& g(int i) { return v[i]; }// ... g(3) = 7; declares the functiong() to return a reference to an integer sog(3)=7 will assign7 to the fourth element of the arrayv[.](#dcl.ref-3.sentence-2)

For another example,struct link { link* next;};

link* first;

void h(link*& p) { // p is a reference to pointer p->next = first;
 first = p;
 p = 0;}void k() { link* q = new link;
 h(q);} declaresp to be a reference to a pointer tolink soh(q) will leaveq with the value zero[.](#dcl.ref-3.sentence-3)

See also [[dcl.init.ref]](dcl.init.ref "9.5.4 References")[.](#dcl.ref-3.sentence-4)

â *end example*]

[4](#dcl.ref-4)

[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/declarations.tex#L3258)

It is unspecified whether or not
a reference requires storage ([[basic.stc]](basic.stc "6.8.6 Storage duration"))[.](#dcl.ref-4.sentence-1)

[5](#dcl.ref-5)

[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/declarations.tex#L3262)

There shall be no references to references,
no arrays of references, and no pointers to references[.](#dcl.ref-5.sentence-1)

The declaration of a reference shall contain an[*initializer*](dcl.init.general#nt:initializer "9.5.1 General [dcl.init.general]") ([[dcl.init.ref]](dcl.init.ref "9.5.4 References"))
except when the declaration contains an explicitextern specifier ([[dcl.stc]](dcl.stc "9.2.2 Storage class specifiers")),
is a class member ([[class.mem]](class.mem "11.4 Class members")) declaration within a class definition,
or is the declaration of a parameter or a return type ([[dcl.fct]](#dcl.fct "9.3.4.6 Functions")); see [[basic.def]](basic.def "6.2 Declarations and definitions")[.](#dcl.ref-5.sentence-2)

[6](#dcl.ref-6)

[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/declarations.tex#L3275)

Attempting to bind a reference to a function where
the converted initializer is a glvalue whose
type is not call-compatible ([[expr.call]](expr.call "7.6.1.3 Function call"))
with the type of the function's definition
results in undefined behavior[.](#dcl.ref-6.sentence-1)

Attempting to bind a reference to an object where
the converted initializer is a glvalue through which
the object is not type-accessible ([[basic.lval]](basic.lval "7.2.1 Value category"))
results in undefined behavior[.](#dcl.ref-6.sentence-2)

[*Note [2](#dcl.ref-note-2)*:

The object designated by such a glvalue can be
outside its lifetime ([[basic.life]](basic.life "6.8.4 Lifetime"))[.](#dcl.ref-6.sentence-3)

Because a null pointer value or a pointer past the end of an object
does not point to an object,
a reference in a well-defined program cannot refer to such things;
see [[expr.unary.op]](expr.unary.op "7.6.2.2 Unary operators")[.](#dcl.ref-6.sentence-4)

As described in [[class.bit]](class.bit "11.4.10 Bit-fields"), a reference cannot be bound directly
to a bit-field[.](#dcl.ref-6.sentence-5)

â *end note*]

The behavior of an evaluation of a reference ([[expr.prim.id]](expr.prim.id "7.5.5 Names"), [[expr.ref]](expr.ref "7.6.1.5 Class member access")) that
does not happen after ([[intro.races]](intro.races "6.10.2.2 Data races")) the initialization of the reference
is undefined[.](#dcl.ref-6.sentence-6)

[*Example [3](#dcl.ref-example-3)*: int &f(int&);int &g();extern int &ir3;int *ip = 0;int &ir1 = *ip; // undefined behavior: null pointerint &ir2 = f(ir3); // undefined behavior: ir3 not yet initializedint &ir3 = g();int &ir4 = f(ir4); // undefined behavior: ir4 used in its own initializerchar x alignas(int);int &ir5 = *reinterpret_cast<int *>(&x); // undefined behavior: initializer refers to char object â *end example*]

[7](#dcl.ref-7)

[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/declarations.tex#L3315)

If a [*typedef-name*](dcl.typedef#nt:typedef-name "9.2.4 The typedef specifier [dcl.typedef]") ([[dcl.typedef]](dcl.typedef "9.2.4 The typedef specifier"), [[temp.param]](temp.param "13.2 Template parameters"))
or a [*decltype-specifier*](dcl.type.decltype#nt:decltype-specifier "9.2.9.6 Decltype specifiers [dcl.type.decltype]") ([[dcl.type.decltype]](dcl.type.decltype "9.2.9.6 Decltype specifiers")) denotes a type TR that
is a reference to a type T, an attempt to create the type âlvalue reference to cv TRâ
creates the type âlvalue reference to Tâ, while an attempt to create
the type ârvalue reference to cv TRâ creates the type TR[.](#dcl.ref-7.sentence-1)

[*Note [3](#dcl.ref-note-3)*:

This rule is known as reference collapsing[.](#dcl.ref-7.sentence-2)

â *end note*]

[*Example [4](#dcl.ref-example-4)*: int i;typedef int& LRI;typedef int&& RRI;

LRI& r1 = i; // r1 has the type int&const LRI& r2 = i; // r2 has the type int&const LRI&& r3 = i; // r3 has the type int& RRI& r4 = i; // r4 has the type int& RRI&& r5 = 5; // r5 has the type int&&decltype(r2)& r6 = i; // r6 has the type int&decltype(r2)&& r7 = i; // r7 has the type int& â *end example*]

[8](#dcl.ref-8)

[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/declarations.tex#L3343)

[*Note [4](#dcl.ref-note-4)*:

Forming a reference to function type is ill-formed if the function
type has [*cv-qualifier*](#nt:cv-qualifier "9.3.1 General [dcl.decl.general]")*s* or a [*ref-qualifier*](#nt:ref-qualifier "9.3.1 General [dcl.decl.general]");
see [[dcl.fct]](#dcl.fct "9.3.4.6 Functions")[.](#dcl.ref-8.sentence-1)

â *end note*]

#### [9.3.4.4](#dcl.mptr) Pointers to members [[dcl.mptr]](dcl.mptr)

[1](#dcl.mptr-1)

[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/declarations.tex#L3354)

The component names of a [*ptr-operator*](#nt:ptr-operator "9.3.1 General [dcl.decl.general]") are
those of its [*nested-name-specifier*](expr.prim.id.qual#nt:nested-name-specifier "7.5.5.3 Qualified names [expr.prim.id.qual]"), if any[.](#dcl.mptr-1.sentence-1)

[2](#dcl.mptr-2)

[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/declarations.tex#L3359)

In a declarationTD whereD has the form

[*nested-name-specifier*](expr.prim.id.qual#nt:nested-name-specifier "7.5.5.3 Qualified names [expr.prim.id.qual]") * [*attribute-specifier-seq*](dcl.attr.grammar#nt:attribute-specifier-seq "9.13.1 Attribute syntax and semantics [dcl.attr.grammar]")opt [*cv-qualifier-seq*](#nt:cv-qualifier-seq "9.3.1 General [dcl.decl.general]")opt D1

and the[*nested-name-specifier*](expr.prim.id.qual#nt:nested-name-specifier "7.5.5.3 Qualified names [expr.prim.id.qual]") designates a class,
and the type of the contained [*declarator-id*](#nt:declarator-id "9.3.1 General [dcl.decl.general]") in the declarationTD1 is â*derived-declarator-type-list*Tâ,
the type of the [*declarator-id*](#nt:declarator-id "9.3.1 General [dcl.decl.general]") inD is â*derived-declarator-type-list* [*cv-qualifier-seq*](#nt:cv-qualifier-seq "9.3.1 General [dcl.decl.general]") pointer to member of class[*nested-name-specifier*](expr.prim.id.qual#nt:nested-name-specifier "7.5.5.3 Qualified names [expr.prim.id.qual]") of typeTâ[.](#dcl.mptr-2.sentence-1)

The optional [*attribute-specifier-seq*](dcl.attr.grammar#nt:attribute-specifier-seq "9.13.1 Attribute syntax and semantics [dcl.attr.grammar]") ([[dcl.attr.grammar]](dcl.attr.grammar "9.13.1 Attribute syntax and semantics")) appertains to the
pointer-to-member[.](#dcl.mptr-2.sentence-2)

The [*nested-name-specifier*](expr.prim.id.qual#nt:nested-name-specifier "7.5.5.3 Qualified names [expr.prim.id.qual]") shall not designate an anonymous union[.](#dcl.mptr-2.sentence-3)

[3](#dcl.mptr-3)

[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/declarations.tex#L3386)

[*Example [1](#dcl.mptr-example-1)*:

struct X {void f(int); int a;};struct Y;

int X::* pmi = &X::a;void (X::* pmf)(int) = &X::f;double X::* pmd;char Y::* pmc; declarespmi,pmf,pmd andpmc to be a pointer to a member ofX of typeint,
a pointer to a member ofX of typevoid(int),
a pointer to a member ofX of typedouble and a pointer to a member ofY of typechar respectively[.](#dcl.mptr-3.sentence-1)

The declaration ofpmd is well-formed even thoughX has no members of typedouble[.](#dcl.mptr-3.sentence-2)

Similarly, the declaration ofpmc is well-formed even thoughY is an incomplete type[.](#dcl.mptr-3.sentence-3)

pmi andpmf can be used like this:X obj;// ... obj.*pmi = 7; // assign 7 to an integer member of obj(obj.*pmf)(7); // call a function member of obj with the argument 7

â *end example*]

[4](#dcl.mptr-4)

[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/declarations.tex#L3446)

A pointer to member shall not point to a static member
of a class ([[class.static]](class.static "11.4.9 Static members")),
a member with reference type,
or
âcv voidâ[.](#dcl.mptr-4.sentence-1)

[5](#dcl.mptr-5)

[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/declarations.tex#L3453)

[*Note [1](#dcl.mptr-note-1)*:

See also [[expr.unary]](expr.unary "7.6.2 Unary expressions") and [[expr.mptr.oper]](expr.mptr.oper "7.6.4 Pointer-to-member operators")[.](#dcl.mptr-5.sentence-1)

The type âpointer to memberâ is distinct from the type âpointerâ,
that is, a pointer to member is declared only by the pointer-to-member
declarator syntax, and never by the pointer declarator syntax[.](#dcl.mptr-5.sentence-2)

There is no âreference-to-memberâ type in C++[.](#dcl.mptr-5.sentence-3)

â *end note*]

#### [9.3.4.5](#dcl.array) Arrays [[dcl.array]](dcl.array)

[1](#dcl.array-1)

[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/declarations.tex#L3465)

In a declaration T D where D has the form

D1 [ [*constant-expression*](expr.const#nt:constant-expression "7.7 Constant expressions [expr.const]")opt ] [*attribute-specifier-seq*](dcl.attr.grammar#nt:attribute-specifier-seq "9.13.1 Attribute syntax and semantics [dcl.attr.grammar]")opt

and the type of the contained [*declarator-id*](#nt:declarator-id "9.3.1 General [dcl.decl.general]") in the declaration T D1 is â*derived-declarator-type-list* Tâ,
the type of the [*declarator-id*](#nt:declarator-id "9.3.1 General [dcl.decl.general]") in D is
â*derived-declarator-type-list* array of N Tâ[.](#dcl.array-1.sentence-1)

The [*constant-expression*](expr.const#nt:constant-expression "7.7 Constant expressions [expr.const]") shall be a converted constant expression of type std​::​size_t ([[expr.const]](expr.const "7.7 Constant expressions"))[.](#dcl.array-1.sentence-2)

Its value N specifies the [*array bound*](#def:array,bound "9.3.4.5 Arrays [dcl.array]"),
i.e., the number of elements in the array;N shall be greater than zero[.](#dcl.array-1.sentence-3)

[2](#dcl.array-2)

[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/declarations.tex#L3482)

In a declaration T D where D has the form

D1 [ ] [*attribute-specifier-seq*](dcl.attr.grammar#nt:attribute-specifier-seq "9.13.1 Attribute syntax and semantics [dcl.attr.grammar]")opt

and the type of the contained [*declarator-id*](#nt:declarator-id "9.3.1 General [dcl.decl.general]") in the declaration T D1 is â*derived-declarator-type-list* Tâ,
the type of the [*declarator-id*](#nt:declarator-id "9.3.1 General [dcl.decl.general]") in D is
â*derived-declarator-type-list* array of unknown bound of Tâ, except as specified below[.](#dcl.array-2.sentence-1)

[3](#dcl.array-3)

[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/declarations.tex#L3493)

A type of the form âarray of N Uâ or
âarray of unknown bound of Uâ is an [*array type*](#def:array_type "9.3.4.5 Arrays [dcl.array]")[.](#dcl.array-3.sentence-1)

The optional [*attribute-specifier-seq*](dcl.attr.grammar#nt:attribute-specifier-seq "9.13.1 Attribute syntax and semantics [dcl.attr.grammar]") appertains to the array type[.](#dcl.array-3.sentence-2)

[4](#dcl.array-4)

[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/declarations.tex#L3501)

U is called the array [*element type*](#def:element_type "9.3.4.5 Arrays [dcl.array]");
this type shall not be
a reference type,
a function type,
an array of unknown bound, orcv void[.](#dcl.array-4.sentence-1)

[*Note [1](#dcl.array-note-1)*:

An array can be constructed
from one of the fundamental types (except void),
from a pointer,
from a pointer to member,
from a class,
from an enumeration type,
or from an array of known bound[.](#dcl.array-4.sentence-2)

â *end note*]

[*Example [1](#dcl.array-example-1)*:

float fa[17], *afp[17]; declares an array of float numbers and
an array of pointers to float numbers[.](#dcl.array-4.sentence-3)

â *end example*]

[5](#dcl.array-5)

[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/declarations.tex#L3525)

Any type of the form
â[*cv-qualifier-seq*](#nt:cv-qualifier-seq "9.3.1 General [dcl.decl.general]") array of N Uâ
is adjusted to
âarray of N [*cv-qualifier-seq*](#nt:cv-qualifier-seq "9.3.1 General [dcl.decl.general]") Uâ,
and similarly for âarray of unknown bound of Uâ[.](#dcl.array-5.sentence-1)

[*Example [2](#dcl.array-example-2)*: typedef int A[5], AA[2][3];typedef const A CA; // type is âarray of 5 const int''typedef const AA CAA; // type is âarray of 2 array of 3 const int'' â *end example*]

[*Note [2](#dcl.array-note-2)*:

An âarray of N [*cv-qualifier-seq*](#nt:cv-qualifier-seq "9.3.1 General [dcl.decl.general]") Uâ
has cv-qualified type; see [[basic.type.qualifier]](basic.type.qualifier "6.9.5 CV-qualifiers")[.](#dcl.array-5.sentence-2)

â *end note*]

[6](#dcl.array-6)

[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/declarations.tex#L3543)

An object of type âarray of N Uâ consists of
a contiguously allocated non-empty set
of N subobjects of type U,
known as the [*elements*](#def:array,element "9.3.4.5 Arrays [dcl.array]") of the array,
and numbered 0 to N-1[.](#dcl.array-6.sentence-1)

[7](#dcl.array-7)

[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/declarations.tex#L3550)

In addition to declarations in which an incomplete object type is allowed,
an array bound may be omitted in some cases in the declaration of a function
parameter ([[dcl.fct]](#dcl.fct "9.3.4.6 Functions"))[.](#dcl.array-7.sentence-1)

An array bound may also be omitted
when an object (but not a non-static data member) of array type is initialized
and the declarator is followed by
an initializer ([[dcl.init]](dcl.init "9.5 Initializers"), [[class.mem]](class.mem "11.4 Class members"), [[expr.type.conv]](expr.type.conv "7.6.1.4 Explicit type conversion (functional notation)"), [[expr.new]](expr.new "7.6.2.8 New"))[.](#dcl.array-7.sentence-2)

In these cases, the array bound is calculated
from the number of initial elements (say, N)
supplied ([[dcl.init.aggr]](dcl.init.aggr "9.5.2 Aggregates")),
and the type of the array is âarray of N Uâ[.](#dcl.array-7.sentence-3)

[8](#dcl.array-8)

[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/declarations.tex#L3564)

Furthermore, if there is a reachable declaration of the entity
that specifies a bound and
has the same host scope ([[basic.scope.scope]](basic.scope.scope "6.4.1 General")),
an omitted array bound is taken to
be the same as in that earlier declaration, and similarly for the definition
of a static data member of a class[.](#dcl.array-8.sentence-1)

[*Example [3](#dcl.array-example-3)*: extern int x[10];struct S {static int y[10];};

int x[]; // OK, bound is 10int S::y[]; // OK, bound is 10void f() {extern int x[]; int i = sizeof(x); // error: incomplete object type}namespace A { extern int z[3]; }int A::z[] = {}; // OK, defines an array of 3 elements â *end example*]

[9](#dcl.array-9)

[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/declarations.tex#L3591)

[*Note [3](#dcl.array-note-3)*:

When several âarray ofâ specifications are adjacent,
a multidimensional array type is created;
only the first of the constant expressions
that specify the bounds of the arrays can be omitted[.](#dcl.array-9.sentence-1)

[*Example [4](#dcl.array-example-4)*:

int x3d[3][5][7]; declares an array of three elements,
each of which is an array of five elements,
each of which is an array of seven integers[.](#dcl.array-9.sentence-2)

The overall array can be viewed as a
three-dimensional array of integers,
with rank 3 ×5 ×7[.](#dcl.array-9.sentence-3)

Any of the expressionsx3d,x3d[i],x3d[i][j],x3d[i][j][k] can reasonably appear in an expression[.](#dcl.array-9.sentence-4)

The expressionx3d[i] is equivalent to*(x3d + i);
in that expression,x3d is subject to the array-to-pointer conversion ([[conv.array]](conv.array "7.3.3 Array-to-pointer conversion"))
and is first converted to
a pointer to a 2-dimensional
array with rank5 ×7 that points to the first element of x3d[.](#dcl.array-9.sentence-5)

Then i is added,
which on typical implementations involves multiplyingi by the
length of the object to which the pointer points,
which is sizeof(int)×5 ×7[.](#dcl.array-9.sentence-6)

The result of the addition and indirection is
an lvalue denoting
the ith array element ofx3d (an array of five arrays of seven integers)[.](#dcl.array-9.sentence-7)

If there is another subscript,
the same argument applies again, sox3d[i][j] is
an lvalue denoting
the jth array element of
the ith array element ofx3d (an array of seven integers), andx3d[i][j][k] is
an lvalue denoting
the kth array element of
the jth array element of
the ith array element ofx3d (an integer)[.](#dcl.array-9.sentence-8)

â *end example*]

The first subscript in the declaration helps determine
the amount of storage consumed by an array
but plays no other part in subscript calculations[.](#dcl.array-9.sentence-9)

â *end note*]

[10](#dcl.array-10)

[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/declarations.tex#L3657)

[*Note [4](#dcl.array-note-4)*:

Conversions affecting expressions of array type are described in [[conv.array]](conv.array "7.3.3 Array-to-pointer conversion")[.](#dcl.array-10.sentence-1)

â *end note*]

[11](#dcl.array-11)

[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/declarations.tex#L3662)

[*Note [5](#dcl.array-note-5)*:

The subscript operator can be overloaded for a class ([[over.sub]](over.sub "12.4.5 Subscripting"))[.](#dcl.array-11.sentence-1)

For the operator's built-in meaning, see [[expr.sub]](expr.sub "7.6.1.2 Subscripting")[.](#dcl.array-11.sentence-2)

â *end note*]

#### [9.3.4.6](#dcl.fct) Functions [[dcl.fct]](dcl.fct)

[1](#dcl.fct-1)

[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/declarations.tex#L3671)

In a declarationTD whereT may be empty andD has the form

D1 ( [*parameter-declaration-clause*](#nt:parameter-declaration-clause "9.3.4.6 Functions [dcl.fct]") ) [*cv-qualifier-seq*](#nt:cv-qualifier-seq "9.3.1 General [dcl.decl.general]")opt  
 [*ref-qualifier*](#nt:ref-qualifier "9.3.1 General [dcl.decl.general]")opt [*noexcept-specifier*](except.spec#nt:noexcept-specifier "14.5 Exception specifications [except.spec]")opt [*attribute-specifier-seq*](dcl.attr.grammar#nt:attribute-specifier-seq "9.13.1 Attribute syntax and semantics [dcl.attr.grammar]")opt [*trailing-return-type*](#nt:trailing-return-type "9.3.1 General [dcl.decl.general]")opt

a *derived-declarator-type-list* is determined as follows:

- [(1.1)](#dcl.fct-1.1)

  If the [*unqualified-id*](expr.prim.id.unqual#nt:unqualified-id "7.5.5.2 Unqualified names [expr.prim.id.unqual]") of the [*declarator-id*](#nt:declarator-id "9.3.1 General [dcl.decl.general]") is a [*conversion-function-id*](class.conv.fct#nt:conversion-function-id "11.4.8.3 Conversion functions [class.conv.fct]"),
the *derived-declarator-type-list* is empty[.](#dcl.fct-1.1.sentence-1)

- [(1.2)](#dcl.fct-1.2)

  Otherwise, the *derived-declarator-type-list* is as appears in
the type â*derived-declarator-type-list* Tâ
of the contained[*declarator-id*](#nt:declarator-id "9.3.1 General [dcl.decl.general]") in the declarationTD1[.](#dcl.fct-1.2.sentence-1)

The declared return type U of the function type
is determined as follows:

- [(1.3)](#dcl.fct-1.3)

  If the [*trailing-return-type*](#nt:trailing-return-type "9.3.1 General [dcl.decl.general]") is present,T shall be the single [*type-specifier*](dcl.type.general#nt:type-specifier "9.2.9.1 General [dcl.type.general]") auto, andU is the type specified by the [*trailing-return-type*](#nt:trailing-return-type "9.3.1 General [dcl.decl.general]")[.](#dcl.fct-1.3.sentence-1)

- [(1.4)](#dcl.fct-1.4)

  Otherwise, if the declaration declares a conversion function,
see [[class.conv.fct]](class.conv.fct "11.4.8.3 Conversion functions")[.](#dcl.fct-1.4.sentence-1)

- [(1.5)](#dcl.fct-1.5)

  Otherwise, U is T[.](#dcl.fct-1.5.sentence-1)

The type of the[*declarator-id*](#nt:declarator-id "9.3.1 General [dcl.decl.general]") inD is
â*derived-declarator-type-list*noexceptopt function of parameter-type-list[*cv-qualifier-seq*](#nt:cv-qualifier-seq "9.3.1 General [dcl.decl.general]")opt [*ref-qualifier*](#nt:ref-qualifier "9.3.1 General [dcl.decl.general]")opt returning Uâ, where

- [(1.6)](#dcl.fct-1.6)

the parameter-type-list is derived from
the [*parameter-declaration-clause*](#nt:parameter-declaration-clause "9.3.4.6 Functions [dcl.fct]") as described below and

- [(1.7)](#dcl.fct-1.7)

the optional noexcept is present if and only if
the exception specification ([[except.spec]](except.spec "14.5 Exception specifications")) is non-throwing[.](#dcl.fct-1.sentence-3)

Such a type is a [*function type*](#def:type,function "9.3.4.6 Functions [dcl.fct]")[.](#dcl.fct-1.sentence-4)[75](#footnote-75 "As indicated by syntax, cv-qualifiers are a significant component in function return types.")

The optional [*attribute-specifier-seq*](dcl.attr.grammar#nt:attribute-specifier-seq "9.13.1 Attribute syntax and semantics [dcl.attr.grammar]") appertains to the function type[.](#dcl.fct-1.sentence-5)

[2](#dcl.fct-2)

[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/declarations.tex#L3740)

[parameter-declaration-clause:](#nt:parameter-declaration-clause "9.3.4.6 Functions [dcl.fct]")  
...  
[*parameter-declaration-list*](#nt:parameter-declaration-list "9.3.4.6 Functions [dcl.fct]")opt  
[*parameter-declaration-list*](#nt:parameter-declaration-list "9.3.4.6 Functions [dcl.fct]") , ...  
[*parameter-declaration-list*](#nt:parameter-declaration-list "9.3.4.6 Functions [dcl.fct]") ...

[parameter-declaration-list:](#nt:parameter-declaration-list "9.3.4.6 Functions [dcl.fct]")  
[*parameter-declaration*](#nt:parameter-declaration "9.3.4.6 Functions [dcl.fct]")  
[*parameter-declaration-list*](#nt:parameter-declaration-list "9.3.4.6 Functions [dcl.fct]") , [*parameter-declaration*](#nt:parameter-declaration "9.3.4.6 Functions [dcl.fct]")

[parameter-declaration:](#nt:parameter-declaration "9.3.4.6 Functions [dcl.fct]")  
[*attribute-specifier-seq*](dcl.attr.grammar#nt:attribute-specifier-seq "9.13.1 Attribute syntax and semantics [dcl.attr.grammar]")opt thisopt [*decl-specifier-seq*](dcl.spec.general#nt:decl-specifier-seq "9.2.1 General [dcl.spec.general]") [*declarator*](#nt:declarator "9.3.1 General [dcl.decl.general]")  
[*attribute-specifier-seq*](dcl.attr.grammar#nt:attribute-specifier-seq "9.13.1 Attribute syntax and semantics [dcl.attr.grammar]")opt [*decl-specifier-seq*](dcl.spec.general#nt:decl-specifier-seq "9.2.1 General [dcl.spec.general]") [*declarator*](#nt:declarator "9.3.1 General [dcl.decl.general]") = [*initializer-clause*](dcl.init.general#nt:initializer-clause "9.5.1 General [dcl.init.general]")  
[*attribute-specifier-seq*](dcl.attr.grammar#nt:attribute-specifier-seq "9.13.1 Attribute syntax and semantics [dcl.attr.grammar]")opt thisopt [*decl-specifier-seq*](dcl.spec.general#nt:decl-specifier-seq "9.2.1 General [dcl.spec.general]") [*abstract-declarator*](#nt:abstract-declarator "9.3.2 Type names [dcl.name]")opt  
[*attribute-specifier-seq*](dcl.attr.grammar#nt:attribute-specifier-seq "9.13.1 Attribute syntax and semantics [dcl.attr.grammar]")opt [*decl-specifier-seq*](dcl.spec.general#nt:decl-specifier-seq "9.2.1 General [dcl.spec.general]") [*abstract-declarator*](#nt:abstract-declarator "9.3.2 Type names [dcl.name]")opt = [*initializer-clause*](dcl.init.general#nt:initializer-clause "9.5.1 General [dcl.init.general]")

The optional [*attribute-specifier-seq*](dcl.attr.grammar#nt:attribute-specifier-seq "9.13.1 Attribute syntax and semantics [dcl.attr.grammar]") in a [*parameter-declaration*](#nt:parameter-declaration "9.3.4.6 Functions [dcl.fct]") appertains to the parameter[.](#dcl.fct-2.sentence-1)

[3](#dcl.fct-3)

[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/declarations.tex#L3767)

The[*parameter-declaration-clause*](#nt:parameter-declaration-clause "9.3.4.6 Functions [dcl.fct]") determines the arguments that can be specified, and their processing, when the function is called[.](#dcl.fct-3.sentence-1)

[*Note [1](#dcl.fct-note-1)*:

The[*parameter-declaration-clause*](#nt:parameter-declaration-clause "9.3.4.6 Functions [dcl.fct]") is used to convert the arguments specified on the function call;
see [[expr.call]](expr.call "7.6.1.3 Function call")[.](#dcl.fct-3.sentence-2)

â *end note*]

If the[*parameter-declaration-clause*](#nt:parameter-declaration-clause "9.3.4.6 Functions [dcl.fct]") is empty, the function takes no arguments[.](#dcl.fct-3.sentence-3)

A parameter list consisting of a single unnamed non-object parameter of
non-dependent type void is equivalent to an empty parameter
list[.](#dcl.fct-3.sentence-4)

Except for this special case, a parameter shall not have type cv void[.](#dcl.fct-3.sentence-5)

A parameter with volatile-qualified type is deprecated;
see [[depr.volatile.type]](depr.volatile.type "D.4 Deprecated volatile types")[.](#dcl.fct-3.sentence-6)

If the[*parameter-declaration-clause*](#nt:parameter-declaration-clause "9.3.4.6 Functions [dcl.fct]")terminates with an ellipsis or a function parameter
pack ([[temp.variadic]](temp.variadic "13.7.4 Variadic templates")), the number of arguments shall be equal
to or greater than the number of parameters that do not have a default
argument and are not function parameter packs[.](#dcl.fct-3.sentence-7)

Where syntactically correct and where â...â is not
part of an [*abstract-declarator*](#nt:abstract-declarator "9.3.2 Type names [dcl.name]"),
â...â
is synonymous with
â, ...â[.](#dcl.fct-3.sentence-8)

A [*parameter-declaration-clause*](#nt:parameter-declaration-clause "9.3.4.6 Functions [dcl.fct]") of the form[*parameter-declaration-list*](#nt:parameter-declaration-list "9.3.4.6 Functions [dcl.fct]") ... is deprecated ([[depr.ellipsis.comma]](depr.ellipsis.comma "D.5 Non-comma-separated ellipsis parameters"))[.](#dcl.fct-3.sentence-9)

[*Example [1](#dcl.fct-example-1)*:

The declarationint printf(const char*, ...); declares a function that can be called with varying numbers and types of arguments[.](#dcl.fct-3.sentence-10)

printf("hello world");
printf("a=%d b=%d", a, b);

However, the first argument must be of a type
that can be converted to aconstchar*[.](#dcl.fct-3.sentence-11)

â *end example*]

[*Note [2](#dcl.fct-note-2)*:

The standard header [<cstdarg>](cstdarg.syn#header:%3ccstdarg%3e "17.14.2 Header <cstdarg> synopsis [cstdarg.syn]") contains a mechanism for accessing arguments passed using the ellipsis
(see [[expr.call]](expr.call "7.6.1.3 Function call") and [[support.runtime]](support.runtime "17.14 Other runtime support"))[.](#dcl.fct-3.sentence-12)

â *end note*]

[4](#dcl.fct-4)

[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/declarations.tex#L3833)

The type of a function is determined using the following rules[.](#dcl.fct-4.sentence-1)

The type of each parameter (including function parameter packs) is
determined from its own [*parameter-declaration*](#nt:parameter-declaration "9.3.4.6 Functions [dcl.fct]") ([dcl.decl])[.](#dcl.fct-4.sentence-2)

After determining the type of each parameter, any parameterof type âarray of Tâ orof function type T is adjusted to be âpointer to Tâ[.](#dcl.fct-4.sentence-3)

After producing the list of parameter types,
any top-level[*cv-qualifier*](#nt:cv-qualifier "9.3.1 General [dcl.decl.general]")*s* modifying a parameter type are deleted
when forming the function type[.](#dcl.fct-4.sentence-4)

The resulting list of transformed parameter types
and the presence or absence of the ellipsis or a function parameter pack
is the function's[*parameter-type-list*](#def:parameter-type-list "9.3.4.6 Functions [dcl.fct]")[.](#dcl.fct-4.sentence-5)

[*Note [3](#dcl.fct-note-3)*:

This transformation does not affect the types of the parameters[.](#dcl.fct-4.sentence-6)

For example, int(*)(const int p, decltype(p)*) andint(*)(int, const int*) are identical types[.](#dcl.fct-4.sentence-7)

â *end note*]

[*Example [2](#dcl.fct-example-2)*: void f(char*); // #1void f(char[]) {} // defines #1void f(const char*) {} // OK, another overloadvoid f(char *const) {} // error: redefines #1void g(char(*)[2]); // #2void g(char[3][2]) {} // defines #2void g(char[3][3]) {} // OK, another overloadvoid h(int x(const int)); // #3void h(int (*)(int)) {} // defines #3 â *end example*]

[5](#dcl.fct-5)

[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/declarations.tex#L3874)

An [*explicit-object-parameter-declaration*](#def:explicit-object-parameter-declaration "9.3.4.6 Functions [dcl.fct]") is
a [*parameter-declaration*](#nt:parameter-declaration "9.3.4.6 Functions [dcl.fct]") with a this specifier[.](#dcl.fct-5.sentence-1)

An explicit-object-parameter-declaration shall appear only as
the first [*parameter-declaration*](#nt:parameter-declaration "9.3.4.6 Functions [dcl.fct]") of
a [*parameter-declaration-list*](#nt:parameter-declaration-list "9.3.4.6 Functions [dcl.fct]") of one of:

- [(5.1)](#dcl.fct-5.1)

a declaration of
a member function or member function template ([[class.mem]](class.mem "11.4 Class members")), or

- [(5.2)](#dcl.fct-5.2)

an explicit instantiation ([[temp.explicit]](temp.explicit "13.9.3 Explicit instantiation")) or
explicit specialization ([[temp.expl.spec]](temp.expl.spec "13.9.4 Explicit specialization")) of
a templated member function, or

- [(5.3)](#dcl.fct-5.3)

a [*lambda-declarator*](expr.prim.lambda.general#nt:lambda-declarator "7.5.6.1 General [expr.prim.lambda.general]") ([[expr.prim.lambda]](expr.prim.lambda "7.5.6 Lambda expressions"))[.](#dcl.fct-5.sentence-2)

A [*member-declarator*](class.mem.general#nt:member-declarator "11.4.1 General [class.mem.general]") with an explicit-object-parameter-declaration
shall not include
a [*ref-qualifier*](#nt:ref-qualifier "9.3.1 General [dcl.decl.general]") or a [*cv-qualifier-seq*](#nt:cv-qualifier-seq "9.3.1 General [dcl.decl.general]") and
shall not be declared static or virtual[.](#dcl.fct-5.sentence-3)

[*Example [3](#dcl.fct-example-3)*: struct C {void f(this C& self); template <typename Self> void g(this Self&& self, int); void h(this C) const; // error: const not allowed here};

void test(C c) { c.f(); // OK, calls C​::​f c.g(42); // OK, calls C​::​g<C&> std::move(c).g(42); // OK, calls C​::​g<C>} â *end example*]

[6](#dcl.fct-6)

[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/declarations.tex#L3912)

A function parameter declared with an explicit-object-parameter-declaration
is an [*explicit object parameter*](#def:parameter,explicit_object "9.3.4.6 Functions [dcl.fct]")[.](#dcl.fct-6.sentence-1)

An explicit object parameter shall not be
a function parameter pack ([[temp.variadic]](temp.variadic "13.7.4 Variadic templates"))[.](#dcl.fct-6.sentence-2)

An [*explicit object member function*](#def:member_function,explicit_object "9.3.4.6 Functions [dcl.fct]") is a non-static member function
with an explicit object parameter[.](#dcl.fct-6.sentence-3)

An [*implicit object member function*](#def:member_function,implicit_object "9.3.4.6 Functions [dcl.fct]") is a non-static member function
without an explicit object parameter[.](#dcl.fct-6.sentence-4)

[7](#dcl.fct-7)

[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/declarations.tex#L3922)

The [*object parameter*](#def:parameter,object "9.3.4.6 Functions [dcl.fct]") of a non-static member function is either
the explicit object parameter or
the implicit object parameter ([[over.match.funcs]](over.match.funcs "12.2.2 Candidate functions and argument lists"))[.](#dcl.fct-7.sentence-1)

[8](#dcl.fct-8)

[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/declarations.tex#L3927)

A [*non-object parameter*](#def:parameter,non-object "9.3.4.6 Functions [dcl.fct]") is a function parameter
that is not the explicit object parameter[.](#dcl.fct-8.sentence-1)

The [*non-object-parameter-type-list*](#def:non-object-parameter-type-list "9.3.4.6 Functions [dcl.fct]") of a member function is
the parameter-type-list of that function with the explicit object parameter,
if any, omitted[.](#dcl.fct-8.sentence-2)

[*Note [4](#dcl.fct-note-4)*:

The non-object-parameter-type-list consists of
the adjusted types of all the non-object parameters[.](#dcl.fct-8.sentence-3)

â *end note*]

[9](#dcl.fct-9)

[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/declarations.tex#L3938)

A function type with a [*cv-qualifier-seq*](#nt:cv-qualifier-seq "9.3.1 General [dcl.decl.general]") or a[*ref-qualifier*](#nt:ref-qualifier "9.3.1 General [dcl.decl.general]") (including a type denoted by[*typedef-name*](dcl.typedef#nt:typedef-name "9.2.4 The typedef specifier [dcl.typedef]") ([[dcl.typedef]](dcl.typedef "9.2.4 The typedef specifier"), [[temp.param]](temp.param "13.2 Template parameters")))
shall appear only as:

- [(9.1)](#dcl.fct-9.1)

the function type for a non-static member function,

- [(9.2)](#dcl.fct-9.2)

the function type to which a pointer to member refers,

- [(9.3)](#dcl.fct-9.3)

the top-level function type of a function typedef declaration
or [*alias-declaration*](dcl.pre#nt:alias-declaration "9.1 Preamble [dcl.pre]"),

- [(9.4)](#dcl.fct-9.4)

the [*type-id*](#nt:type-id "9.3.2 Type names [dcl.name]") in the default argument of a[*type-parameter*](temp.param#nt:type-parameter "13.2 Template parameters [temp.param]") ([[temp.param]](temp.param "13.2 Template parameters")),

- [(9.5)](#dcl.fct-9.5)

the [*type-id*](#nt:type-id "9.3.2 Type names [dcl.name]") of a [*template-argument*](temp.names#nt:template-argument "13.3 Names of template specializations [temp.names]") for a[*type-parameter*](temp.param#nt:type-parameter "13.2 Template parameters [temp.param]") ([[temp.arg.type]](temp.arg.type "13.4.2 Type template arguments")), or

- [(9.6)](#dcl.fct-9.6)

the operand of a [*reflect-expression*](expr.reflect#nt:reflect-expression "7.6.2.10 The reflection operator [expr.reflect]") ([[expr.reflect]](expr.reflect "7.6.2.10 The reflection operator"))[.](#dcl.fct-9.sentence-1)

[*Example [4](#dcl.fct-example-4)*: typedef int FIC(int) const;
FIC f; // error: does not declare a member functionstruct S { FIC f; // OK};
FIC S::*pm = &S::f; // OKconstexpr std::meta::info yeti = ^^void(int) const &; // OK â *end example*]

[10](#dcl.fct-10)

[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/declarations.tex#L3971)

The effect of a[*cv-qualifier-seq*](#nt:cv-qualifier-seq "9.3.1 General [dcl.decl.general]") in a function declarator is not the same as
adding cv-qualification on top of the function type[.](#dcl.fct-10.sentence-1)

In the latter case, the cv-qualifiers are ignored[.](#dcl.fct-10.sentence-2)

[*Note [5](#dcl.fct-note-5)*:

A function type that has a [*cv-qualifier-seq*](#nt:cv-qualifier-seq "9.3.1 General [dcl.decl.general]") is not a
cv-qualified type; there are no cv-qualified function types[.](#dcl.fct-10.sentence-3)

â *end note*]

[*Example [5](#dcl.fct-example-5)*: typedef void F();struct S {const F f; // OK, equivalent to: void f();}; â *end example*]

[11](#dcl.fct-11)

[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/declarations.tex#L3990)

The return type, the parameter-type-list, the [*ref-qualifier*](#nt:ref-qualifier "9.3.1 General [dcl.decl.general]"),
the [*cv-qualifier-seq*](#nt:cv-qualifier-seq "9.3.1 General [dcl.decl.general]"), and
the exception specification,
but not the default arguments ([[dcl.fct.default]](#dcl.fct.default "9.3.4.7 Default arguments"))
or the trailing [*requires-clause*](temp.pre#nt:requires-clause "13.1 Preamble [temp.pre]") ([dcl.decl]),
are part of the function type[.](#dcl.fct-11.sentence-1)

[*Note [6](#dcl.fct-note-6)*:

Function types are checked during the assignments and initializations of
pointers to functions, references to functions, and pointers to member functions[.](#dcl.fct-11.sentence-2)

â *end note*]

[12](#dcl.fct-12)

[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/declarations.tex#L4002)

[*Example [6](#dcl.fct-example-6)*:

The declarationint fseek(FILE*, long, int); declares a function taking three arguments of the specified types,
and returningint ([[dcl.type]](dcl.type "9.2.9 Type specifiers"))[.](#dcl.fct-12.sentence-1)

â *end example*]

[13](#dcl.fct-13)

[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/declarations.tex#L4013)

[*Note [7](#dcl.fct-note-7)*:

A single name can be used for several different functions in a single scope;
this is function overloading ([[over]](over "12 Overloading"))[.](#dcl.fct-13.sentence-1)

â *end note*]

[14](#dcl.fct-14)

[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/declarations.tex#L4020)

The return type shall be a non-array object type, a reference type, or cv void[.](#dcl.fct-14.sentence-1)

[*Note [8](#dcl.fct-note-8)*:

An array of placeholder type is considered an array type[.](#dcl.fct-14.sentence-2)

â *end note*]

[15](#dcl.fct-15)

[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/declarations.tex#L4028)

A volatile-qualified return type is deprecated;
see [[depr.volatile.type]](depr.volatile.type "D.4 Deprecated volatile types")[.](#dcl.fct-15.sentence-1)

[16](#dcl.fct-16)

[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/declarations.tex#L4032)

Types shall not be defined in return or parameter types[.](#dcl.fct-16.sentence-1)

[17](#dcl.fct-17)

[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/declarations.tex#L4035)

A typedef of function type may be used to declare a function but shall not be
used to define a function ([[dcl.fct.def]](dcl.fct.def "9.6 Function definitions"))[.](#dcl.fct-17.sentence-1)

[*Example [7](#dcl.fct-example-7)*: typedef void F();
F fv; // OK, equivalent to void fv(); F fv { } // errorvoid fv() { } // OK, definition of fv â *end example*]

[18](#dcl.fct-18)

[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/declarations.tex#L4048)

An identifier can optionally be provided as a parameter name;
if present in a function definition ([[dcl.fct.def]](dcl.fct.def "9.6 Function definitions")), it names a parameter[.](#dcl.fct-18.sentence-1)

[*Note [9](#dcl.fct-note-9)*:

In particular, parameter names are also optional in function definitions
and names used for a parameter in different declarations and the definition
of a function need not be the same[.](#dcl.fct-18.sentence-2)

â *end note*]

[19](#dcl.fct-19)

[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/declarations.tex#L4057)

[*Example [8](#dcl.fct-example-8)*:

The declarationint i, *pi,
 f(), *fpi(int), (*pif)(const char*, const char*), (*fpif(int))(int); declares an integeri,
a pointerpi to an integer,
a functionf taking no arguments and returning an integer,
a functionfpi taking an integer argument and returning a pointer to an integer,
a pointerpif to a function which
takes two pointers to constant characters and returns an integer,
a functionfpif taking an integer argument and returning a pointer to a function that takes an integer argument and returns an integer[.](#dcl.fct-19.sentence-1)

It is especially useful to comparefpi andpif[.](#dcl.fct-19.sentence-2)

The binding of*fpi(int) is*(fpi(int)),
so the declaration suggests,
and the same construction in an expression
requires, the calling of a functionfpi,
and then using indirection through the (pointer) result
to yield an integer[.](#dcl.fct-19.sentence-3)

In the declarator(*pif)(const char*, const char*),
the extra parentheses are necessary to indicate that indirection through
a pointer to a function yields a function, which is then called[.](#dcl.fct-19.sentence-4)

â *end example*]

[*Note [10](#dcl.fct-note-10)*:

Typedefs and [*trailing-return-type*](#nt:trailing-return-type "9.3.1 General [dcl.decl.general]")*s* are sometimes convenient when the return type of a function is complex[.](#dcl.fct-19.sentence-5)

For example,
the functionfpif above can be declaredtypedef int IFUNC(int);
IFUNC* fpif(int); orauto fpif(int)->int(*)(int);

A [*trailing-return-type*](#nt:trailing-return-type "9.3.1 General [dcl.decl.general]") is most useful for a type that would be more complicated to specify before the [*declarator-id*](#nt:declarator-id "9.3.1 General [dcl.decl.general]"):template <class T, class U> auto add(T t, U u) -> decltype(t + u); rather thantemplate <class T, class U> decltype((*(T*)0) + (*(U*)0)) add(T t, U u);

â *end note*]

[20](#dcl.fct-20)

[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/declarations.tex#L4130)

A [*non-template function*](#def:function,non-template "9.3.4.6 Functions [dcl.fct]") is a function that is not a function template
specialization[.](#dcl.fct-20.sentence-1)

[*Note [11](#dcl.fct-note-11)*:

A function template is not a function[.](#dcl.fct-20.sentence-2)

â *end note*]

[21](#dcl.fct-21)

[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/declarations.tex#L4137)

An [*abbreviated function template*](#def:template,function,abbreviated "9.3.4.6 Functions [dcl.fct]") is a function declaration that has
one or more generic parameter type placeholders ([[dcl.spec.auto]](dcl.spec.auto "9.2.9.7 Placeholder type specifiers"))[.](#dcl.fct-21.sentence-1)

An abbreviated function template is equivalent to
a function template ([[temp.fct]](temp.fct "13.7.7 Function templates"))
whose [*template-parameter-list*](temp.pre#nt:template-parameter-list "13.1 Preamble [temp.pre]") includes
one invented [*type-parameter*](temp.param#nt:type-parameter "13.2 Template parameters [temp.param]") for each generic parameter type placeholder
of the function declaration, in order of appearance[.](#dcl.fct-21.sentence-2)

For a [*placeholder-type-specifier*](dcl.spec.auto.general#nt:placeholder-type-specifier "9.2.9.7.1 General [dcl.spec.auto.general]") of the form auto,
the invented parameter is
an unconstrained [*type-parameter*](temp.param#nt:type-parameter "13.2 Template parameters [temp.param]")[.](#dcl.fct-21.sentence-3)

For a [*placeholder-type-specifier*](dcl.spec.auto.general#nt:placeholder-type-specifier "9.2.9.7.1 General [dcl.spec.auto.general]") of the form[*type-constraint*](temp.param#nt:type-constraint "13.2 Template parameters [temp.param]") auto,
the invented parameter is a [*type-parameter*](temp.param#nt:type-parameter "13.2 Template parameters [temp.param]") with
that [*type-constraint*](temp.param#nt:type-constraint "13.2 Template parameters [temp.param]")[.](#dcl.fct-21.sentence-4)

The invented [*type-parameter*](temp.param#nt:type-parameter "13.2 Template parameters [temp.param]") declares
a template parameter pack
if the corresponding [*parameter-declaration*](#nt:parameter-declaration "9.3.4.6 Functions [dcl.fct]") declares a function parameter pack[.](#dcl.fct-21.sentence-5)

If the placeholder contains decltype(auto),
the program is ill-formed[.](#dcl.fct-21.sentence-6)

The adjusted function parameters of an abbreviated function template
are derived from the [*parameter-declaration-clause*](#nt:parameter-declaration-clause "9.3.4.6 Functions [dcl.fct]") by
replacing each occurrence of a placeholder with
the name of the corresponding invented [*type-parameter*](temp.param#nt:type-parameter "13.2 Template parameters [temp.param]")[.](#dcl.fct-21.sentence-7)

[*Example [9](#dcl.fct-example-9)*: template<typename T> concept C1 = /* ... */;template<typename T> concept C2 = /* ... */;template<typename... Ts> concept C3 = /* ... */;

void g1(const C1 auto*, C2 auto&);void g2(C1 auto&...);void g3(C3 auto...);void g4(C3 auto);

The declarations above are functionally equivalent (but not equivalent) to
their respective declarations below:template<C1 T, C2 U> void g1(const T*, U&);template<C1... Ts> void g2(Ts&...);template<C3... Ts> void g3(Ts...);template<C3 T> void g4(T);

Abbreviated function templates can be specialized like all function templates[.](#dcl.fct-21.sentence-9)

template<> void g1<int>(const int*, const double&); // OK, specialization of g1<int, const double> â *end example*]

[22](#dcl.fct-22)

[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/declarations.tex#L4190)

An abbreviated function template can have a [*template-head*](temp.pre#nt:template-head "13.1 Preamble [temp.pre]")[.](#dcl.fct-22.sentence-1)

The invented [*type-parameter*](temp.param#nt:type-parameter "13.2 Template parameters [temp.param]")*s* are
appended to the [*template-parameter-list*](temp.pre#nt:template-parameter-list "13.1 Preamble [temp.pre]") after
the explicitly declared [*template-parameter*](temp.param#nt:template-parameter "13.2 Template parameters [temp.param]")*s*[.](#dcl.fct-22.sentence-2)

[*Example [10](#dcl.fct-example-10)*: template<typename> concept C = /* ... */;

template <typename T, C U>void g(T x, U y, C auto z);

This is functionally equivalent to each of the following two declarations[.](#dcl.fct-22.sentence-3)

template<typename T, C U, C W>void g(T x, U y, W z);

template<typename T, typename U, typename W>requires C<U> && C<W>void g(T x, U y, W z); â *end example*]

[23](#dcl.fct-23)

[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/declarations.tex#L4214)

A function declaration at block scope
shall not declare an abbreviated function template[.](#dcl.fct-23.sentence-1)

[24](#dcl.fct-24)

[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/declarations.tex#L4218)

A [*declarator-id*](#nt:declarator-id "9.3.1 General [dcl.decl.general]") or [*abstract-declarator*](#nt:abstract-declarator "9.3.2 Type names [dcl.name]") containing an ellipsis shall only
be used in a [*parameter-declaration*](#nt:parameter-declaration "9.3.4.6 Functions [dcl.fct]")[.](#dcl.fct-24.sentence-1)

When it is part of a[*parameter-declaration-clause*](#nt:parameter-declaration-clause "9.3.4.6 Functions [dcl.fct]"),
the [*parameter-declaration*](#nt:parameter-declaration "9.3.4.6 Functions [dcl.fct]") declares a
function parameter pack ([[temp.variadic]](temp.variadic "13.7.4 Variadic templates"))[.](#dcl.fct-24.sentence-2)

Otherwise, the [*parameter-declaration*](#nt:parameter-declaration "9.3.4.6 Functions [dcl.fct]") is part of a[*template-parameter-list*](temp.pre#nt:template-parameter-list "13.1 Preamble [temp.pre]") and declares a
template parameter pack; see [[temp.param]](temp.param "13.2 Template parameters")[.](#dcl.fct-24.sentence-3)

A function parameter pack is a pack expansion ([[temp.variadic]](temp.variadic "13.7.4 Variadic templates"))[.](#dcl.fct-24.sentence-4)

[*Example [11](#dcl.fct-example-11)*: template<typename... T> void f(T (* ...t)(int, int));

int add(int, int);float subtract(int, int);

void g() { f(add, subtract);} â *end example*]

[25](#dcl.fct-25)

[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/declarations.tex#L4243)

There is a syntactic ambiguity when an ellipsis occurs at the end
of a [*parameter-declaration-clause*](#nt:parameter-declaration-clause "9.3.4.6 Functions [dcl.fct]") without a preceding
comma[.](#dcl.fct-25.sentence-1)

In this case, the ellipsis is parsed as part of the[*abstract-declarator*](#nt:abstract-declarator "9.3.2 Type names [dcl.name]") if the type of the parameter either names
a template parameter pack that has not been expanded or contains auto;
otherwise, it is
parsed as part of the [*parameter-declaration-clause*](#nt:parameter-declaration-clause "9.3.4.6 Functions [dcl.fct]")[.](#dcl.fct-25.sentence-2)[76](#footnote-76 "One can explicitly disambiguate the parse either by introducing a comma (so the ellipsis will be parsed as part of the parameter-declaration-clause) or by introducing a name for the parameter (so the ellipsis will be parsed as part of the declarator-id).")

[75)](#footnote-75)[75)](#footnoteref-75)

As indicated by syntax, cv-qualifiers are a significant component in function return types[.](#footnote-75.sentence-1)

[76)](#footnote-76)[76)](#footnoteref-76)

One can explicitly disambiguate the parse either by
introducing a comma (so the ellipsis will be parsed as part of the[*parameter-declaration-clause*](#nt:parameter-declaration-clause "9.3.4.6 Functions [dcl.fct]")) or by introducing a name for the
parameter (so the ellipsis will be parsed as part of the[*declarator-id*](#nt:declarator-id "9.3.1 General [dcl.decl.general]"))[.](#footnote-76.sentence-1)

#### [9.3.4.7](#dcl.fct.default) Default arguments [[dcl.fct.default]](dcl.fct.default)

[1](#dcl.fct.default-1)

[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/declarations.tex#L4263)

If an [*initializer-clause*](dcl.init.general#nt:initializer-clause "9.5.1 General [dcl.init.general]") is specified in a[*parameter-declaration*](#nt:parameter-declaration "9.3.4.6 Functions [dcl.fct]") this[*initializer-clause*](dcl.init.general#nt:initializer-clause "9.5.1 General [dcl.init.general]") is used as a default argument[.](#dcl.fct.default-1.sentence-1)

[*Note [1](#dcl.fct.default-note-1)*:

Default arguments will be used in calls
where trailing arguments are missing ([[expr.call]](expr.call "7.6.1.3 Function call"))[.](#dcl.fct.default-1.sentence-2)

â *end note*]

[2](#dcl.fct.default-2)

[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/declarations.tex#L4273)

[*Example [1](#dcl.fct.default-example-1)*:

The declarationvoid point(int = 3, int = 4); declares a function that can be called with zero, one, or two arguments of typeint[.](#dcl.fct.default-2.sentence-1)

It can be called in any of these ways:point(1,2); point(1); point();

The last two calls are equivalent topoint(1,4) andpoint(3,4),
respectively[.](#dcl.fct.default-2.sentence-3)

â *end example*]

[3](#dcl.fct.default-3)

[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/declarations.tex#L4294)

A default argument shall be specified only in the[*parameter-declaration-clause*](#nt:parameter-declaration-clause "9.3.4.6 Functions [dcl.fct]") of a function declaration
or [*lambda-declarator*](expr.prim.lambda.general#nt:lambda-declarator "7.5.6.1 General [expr.prim.lambda.general]") or in a[*template-parameter*](temp.param#nt:template-parameter "13.2 Template parameters [temp.param]") ([[temp.param]](temp.param "13.2 Template parameters"))[.](#dcl.fct.default-3.sentence-1)

A default argument shall not be specified for
a template parameter pack or
a function parameter pack[.](#dcl.fct.default-3.sentence-2)

If it is specified in a[*parameter-declaration-clause*](#nt:parameter-declaration-clause "9.3.4.6 Functions [dcl.fct]"),
it shall not occur within a[*declarator*](#nt:declarator "9.3.1 General [dcl.decl.general]") or[*abstract-declarator*](#nt:abstract-declarator "9.3.2 Type names [dcl.name]") of a[*parameter-declaration*](#nt:parameter-declaration "9.3.4.6 Functions [dcl.fct]")[.](#dcl.fct.default-3.sentence-3)[77](#footnote-77 "This means that default arguments cannot appear, for example, in declarations of pointers to functions, references to functions, or typedef declarations.")

[4](#dcl.fct.default-4)

[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/declarations.tex#L4321)

For non-template functions, default arguments can be added in later
declarations of a
function that have the same host scope[.](#dcl.fct.default-4.sentence-1)

Declarations that have different
host scopes have completely distinct sets of default arguments[.](#dcl.fct.default-4.sentence-2)

That
is, declarations in inner scopes do not acquire default
arguments from declarations in outer scopes, and vice versa[.](#dcl.fct.default-4.sentence-3)

In
a given function declaration, each parameter subsequent to a
parameter with a default argument shall have a default argument
supplied in this or a previous declaration,
unless the parameter was expanded from a parameter pack,
or shall be a function parameter pack[.](#dcl.fct.default-4.sentence-4)

[*Note [2](#dcl.fct.default-note-2)*:

A default argument
cannot be redefined by a later declaration
(not even to the same value) ([[basic.def.odr]](basic.def.odr "6.3 One-definition rule"))[.](#dcl.fct.default-4.sentence-5)

â *end note*]

[*Example [2](#dcl.fct.default-example-2)*: void g(int = 0, ...); // OK, ellipsis is not a parameter so it can follow// a parameter with a default argumentvoid f(int, int);void f(int, int = 7);void h() { f(3); // OK, calls f(3, 7)void f(int = 1, int); // error: does not use default from surrounding scope}void m() {void f(int, int); // has no defaults f(4); // error: wrong number of argumentsvoid f(int, int = 5); // OK f(4); // OK, calls f(4, 5);void f(int, int = 5); // error: cannot redefine, even to same value}void n() { f(6); // OK, calls f(6, 7)}template<class ... T> struct C {void f(int n = 0, T...);};
C<int> c; // OK, instantiates declaration void C​::​f(int n = 0, int) â *end example*]

For a given inline function defined in different translation units,
the accumulated sets of default arguments at the end of the
translation units shall be the same; no diagnostic is required[.](#dcl.fct.default-4.sentence-6)

If a friend declaration D specifies a default argument expression,
that declaration shall be a definition and there shall be no other
declaration of the function or function template
which is reachable from D or from which D is reachable[.](#dcl.fct.default-4.sentence-7)

[5](#dcl.fct.default-5)

[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/declarations.tex#L4375)

The default argument has the
same semantic constraints as the initializer in a
declaration of a variable of the parameter type, using the
copy-initialization semantics ([[dcl.init]](dcl.init "9.5 Initializers"))[.](#dcl.fct.default-5.sentence-1)

The names in the
default argument are looked up, and the semantic constraints are checked,
at the point where the default argument appears, except that
an immediate invocation ([[expr.const]](expr.const "7.7 Constant expressions")) that
is a potentially-evaluated subexpression ([[intro.execution]](intro.execution "6.10.1 Sequential execution")) of
the [*initializer-clause*](dcl.init.general#nt:initializer-clause "9.5.1 General [dcl.init.general]") in a [*parameter-declaration*](#nt:parameter-declaration "9.3.4.6 Functions [dcl.fct]") is
neither evaluated
nor checked for whether it is a constant expression at that point[.](#dcl.fct.default-5.sentence-2)

Name lookup and checking of semantic constraints for default
arguments of templated functions are performed as described in [[temp.inst]](temp.inst "13.9.2 Implicit instantiation")[.](#dcl.fct.default-5.sentence-3)

[*Example [3](#dcl.fct.default-example-3)*:

In the following code,g will be called with the valuef(2):int a = 1;int f(int);int g(int x = f(a)); // default argument: f(​::​a)void h() { a = 2; {int a = 3;
 g(); // g(f(​::​a))}}

â *end example*]

[*Note [3](#dcl.fct.default-note-3)*:

A default argument is a complete-class context ([[class.mem]](class.mem "11.4 Class members"))[.](#dcl.fct.default-5.sentence-5)

Access checking applies to names in default arguments as
described in [[class.access]](class.access "11.8 Member access control")[.](#dcl.fct.default-5.sentence-6)

â *end note*]

[6](#dcl.fct.default-6)

[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/declarations.tex#L4419)

Except for member functions of templated classes, the
default arguments in a member function definition that appears
outside of the class definition
are added to the set of default arguments provided by the
member function declaration in the class definition;
the program is ill-formed if a default constructor ([[class.default.ctor]](class.default.ctor "11.4.5.2 Default constructors")),
copy or move constructor ([[class.copy.ctor]](class.copy.ctor "11.4.5.3 Copy/move constructors")), or
copy or move assignment operator ([[class.copy.assign]](class.copy.assign "11.4.6 Copy/move assignment operator"))
is so declared[.](#dcl.fct.default-6.sentence-1)

Default arguments for a member function of a templated class
shall be specified on the initial declaration of the member
function within the templated class[.](#dcl.fct.default-6.sentence-2)

[*Example [4](#dcl.fct.default-example-4)*: class C {void f(int i = 3); void g(int i, int j = 99);};

void C::f(int i = 3) {} // error: default argument already specified in class scopevoid C::g(int i = 88, int j) {} // in this translation unit, C​::​g can be called with no arguments â *end example*]

[7](#dcl.fct.default-7)

[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/declarations.tex#L4444)

[*Note [4](#dcl.fct.default-note-4)*:

A local variable cannot be odr-used ([[basic.def.odr]](basic.def.odr#term.odr.use "6.3 One-definition rule"))
in a default argument[.](#dcl.fct.default-7.sentence-1)

â *end note*]

[*Example [5](#dcl.fct.default-example-5)*: void f() {int i; extern void g(int x = i); // errorextern void h(int x = sizeof(i)); // OK// ...} â *end example*]

[8](#dcl.fct.default-8)

[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/declarations.tex#L4460)

[*Note [5](#dcl.fct.default-note-5)*:

The keywordthis cannot appear in a default argument of a member function;
see [[expr.prim.this]](expr.prim.this "7.5.3 This")[.](#dcl.fct.default-8.sentence-1)

[*Example [6](#dcl.fct.default-example-6)*: class A {void f(A* p = this) { } // error}; â *end example*]

â *end note*]

[9](#dcl.fct.default-9)

[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/declarations.tex#L4475)

A default argument is evaluated each time the function is called
with no argument for the corresponding parameter[.](#dcl.fct.default-9.sentence-1)

A parameter shall not appear as a potentially-evaluated expression
in a default argument[.](#dcl.fct.default-9.sentence-2)

[*Note [6](#dcl.fct.default-note-6)*:

Parameters of a function declared before a default argument
are in scope and can hide namespace and class member names[.](#dcl.fct.default-9.sentence-3)

â *end note*]

[*Example [7](#dcl.fct.default-example-7)*: int a;int f(int a, int b = a); // error: parameter a used as default argumenttypedef int I;int g(float I, int b = I(2)); // error: parameter I foundint h(int a, int b = sizeof(a)); // OK, [unevaluated operand](expr.context#def:unevaluated_operand "7.2.3 Context dependence [expr.context]") â *end example*]

A non-static member shall not be designated in a default argument unless

- [(9.1)](#dcl.fct.default-9.1)

it is designated by
the [*id-expression*](expr.prim.id.general#nt:id-expression "7.5.5.1 General [expr.prim.id.general]") or [*splice-expression*](expr.prim.splice#nt:splice-expression "7.5.9 Expression splicing [expr.prim.splice]") of a class member access expression ([[expr.ref]](expr.ref "7.6.1.5 Class member access")),

- [(9.2)](#dcl.fct.default-9.2)

it is designated by an expression
used to form a pointer to member ([[expr.unary.op]](expr.unary.op "7.6.2.2 Unary operators")), or

- [(9.3)](#dcl.fct.default-9.3)

it appears as the operand of
a [*reflect-expression*](expr.reflect#nt:reflect-expression "7.6.2.10 The reflection operator [expr.reflect]") ([[expr.reflect]](expr.reflect "7.6.2.10 The reflection operator"))[.](#dcl.fct.default-9.sentence-4)

[*Example [8](#dcl.fct.default-example-8)*:

The declaration ofX​::​mem1() in the following example is ill-formed because no object is supplied for the
non-static memberX​::​a used as an initializer[.](#dcl.fct.default-9.sentence-5)

int b;class X {int a; int mem1(int i = a); // error: non-static member a used as default argumentint mem2(int i = b); // OK, use X​::​bconsteval void mem3(std::meta::info r = ^^a) {} // OKint mem4(int i = [:^^a:]); // error: non-static member a designated in default argumentstatic int b;};

The declaration ofX​::​mem2() is meaningful, however, since no object is needed to access the static memberX​::​b[.](#dcl.fct.default-9.sentence-6)

Classes, objects, and members are described in [[class]](class "11 Classes")[.](#dcl.fct.default-9.sentence-7)

â *end example*]

A default argument is not part of the
type of a function[.](#dcl.fct.default-9.sentence-8)

[*Example [9](#dcl.fct.default-example-9)*: int f(int = 0);

void h() {int j = f(1); int k = f(); // OK, means f(0)}int (*p1)(int) = &f;int (*p2)() = &f; // error: type mismatch â *end example*]

[*Note [7](#dcl.fct.default-note-7)*:

When an overload set contains a declaration of a function
whose host scope is S,
any default argument associated with any reachable declaration
whose host scope is S is available to the call ([[over.match.viable]](over.match.viable "12.2.3 Viable functions"))[.](#dcl.fct.default-9.sentence-9)

â *end note*]

[*Note [8](#dcl.fct.default-note-8)*:

The candidate might have been found through a [*using-declarator*](namespace.udecl#nt:using-declarator "9.10 The using declaration [namespace.udecl]") from which the declaration that provides the default argument is not reachable[.](#dcl.fct.default-9.sentence-10)

â *end note*]

[10](#dcl.fct.default-10)

[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/declarations.tex#L4560)

A virtual function call ([[class.virtual]](class.virtual "11.7.3 Virtual functions")) uses the default
arguments in the declaration of the virtual function determined
by the static type of the pointer or reference denoting the
object[.](#dcl.fct.default-10.sentence-1)

An overriding function in a derived class does not
acquire default arguments from the function it overrides[.](#dcl.fct.default-10.sentence-2)

[*Example [10](#dcl.fct.default-example-10)*: struct A {virtual void f(int a = 7);};struct B : public A {void f(int a);};void m() { B* pb = new B;
 A* pa = pb;
 pa->f(); // OK, calls pa->B​::​f(7) pb->f(); // error: wrong number of arguments for B​::​f()} â *end example*]

[77)](#footnote-77)[77)](#footnoteref-77)

This means that default
arguments cannot appear,
for example, in declarations of pointers to functions,
references to functions, ortypedef declarations[.](#footnote-77.sentence-1)
