[dcl.type]

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

## 9.2 Specifiers [[dcl.spec]](dcl.spec#dcl.type)

### 9.2.9 Type specifiers [dcl.type]

#### [9.2.9.1](#general) General [[dcl.type.general]](dcl.type.general)

[1](#general-1)

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

The type-specifiers are

[type-specifier:](#nt:type-specifier "9.2.9.1 General [dcl.type.general]")  
[*simple-type-specifier*](#nt:simple-type-specifier "9.2.9.3 Simple type specifiers [dcl.type.simple]")  
[*elaborated-type-specifier*](#nt:elaborated-type-specifier "9.2.9.5 Elaborated type specifiers [dcl.type.elab]")  
[*typename-specifier*](temp.res.general#nt:typename-specifier "13.8.1 General [temp.res.general]")  
[*cv-qualifier*](dcl.decl.general#nt:cv-qualifier "9.3.1 General [dcl.decl.general]")

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

[defining-type-specifier:](#nt:defining-type-specifier "9.2.9.1 General [dcl.type.general]")  
[*type-specifier*](#nt:type-specifier "9.2.9.1 General [dcl.type.general]")  
[*class-specifier*](class.pre#nt:class-specifier "11.1 Preamble [class.pre]")  
[*enum-specifier*](dcl.enum#nt:enum-specifier "9.8.1 Enumeration declarations [dcl.enum]")

[defining-type-specifier-seq:](#nt:defining-type-specifier-seq "9.2.9.1 General [dcl.type.general]")  
[*defining-type-specifier*](#nt:defining-type-specifier "9.2.9.1 General [dcl.type.general]") [*attribute-specifier-seq*](dcl.attr.grammar#nt:attribute-specifier-seq "9.13.1 Attribute syntax and semantics [dcl.attr.grammar]")opt  
[*defining-type-specifier*](#nt:defining-type-specifier "9.2.9.1 General [dcl.type.general]") [*defining-type-specifier-seq*](#nt:defining-type-specifier-seq "9.2.9.1 General [dcl.type.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 [*type-specifier-seq*](#nt:type-specifier-seq "9.2.9.1 General [dcl.type.general]") or a [*defining-type-specifier-seq*](#nt:defining-type-specifier-seq "9.2.9.1 General [dcl.type.general]") appertains
to the type denoted by the preceding [*type-specifier*](#nt:type-specifier "9.2.9.1 General [dcl.type.general]")*s* or [*defining-type-specifier*](#nt:defining-type-specifier "9.2.9.1 General [dcl.type.general]")*s* ([[dcl.meaning]](dcl.meaning "9.3.4 Meaning of declarators"))[.](#general-1.sentence-2)

The[*attribute-specifier-seq*](dcl.attr.grammar#nt:attribute-specifier-seq "9.13.1 Attribute syntax and semantics [dcl.attr.grammar]") affects the type only for the declaration it appears in,
not other declarations involving the same type[.](#general-1.sentence-3)

[2](#general-2)

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

As a general rule, at most one[*defining-type-specifier*](#nt:defining-type-specifier "9.2.9.1 General [dcl.type.general]") is allowed in the complete[*decl-specifier-seq*](dcl.spec.general#nt:decl-specifier-seq "9.2.1 General [dcl.spec.general]") of a [*declaration*](dcl.pre#nt:declaration "9.1 Preamble [dcl.pre]") or in a[*defining-type-specifier-seq*](#nt:defining-type-specifier-seq "9.2.9.1 General [dcl.type.general]"),
and at most one[*type-specifier*](#nt:type-specifier "9.2.9.1 General [dcl.type.general]") is allowed in a[*type-specifier-seq*](#nt:type-specifier-seq "9.2.9.1 General [dcl.type.general]")[.](#general-2.sentence-1)

The only exceptions to this rule are the following:

- [(2.1)](#general-2.1)

  const can be combined with any type specifier except itself[.](#general-2.1.sentence-1)

- [(2.2)](#general-2.2)

  volatile can be combined with any type specifier except itself[.](#general-2.2.sentence-1)

- [(2.3)](#general-2.3)

  signed or unsigned can be combined withchar, long, short, or int[.](#general-2.3.sentence-1)

- [(2.4)](#general-2.4)

  short or long can be combined with int[.](#general-2.4.sentence-1)

- [(2.5)](#general-2.5)

  long can be combined with double[.](#general-2.5.sentence-1)

- [(2.6)](#general-2.6)

  long can be combined with long[.](#general-2.6.sentence-1)

[3](#general-3)

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

Except in a declaration of a constructor, destructor, or conversion
function, at least one [*defining-type-specifier*](#nt:defining-type-specifier "9.2.9.1 General [dcl.type.general]") that is not a[*cv-qualifier*](dcl.decl.general#nt:cv-qualifier "9.3.1 General [dcl.decl.general]") shall appear in a complete[*type-specifier-seq*](#nt:type-specifier-seq "9.2.9.1 General [dcl.type.general]") or a complete[*decl-specifier-seq*](dcl.spec.general#nt:decl-specifier-seq "9.2.1 General [dcl.spec.general]")[.](#general-3.sentence-1)[74](#footnote-74 "There is no special provision for a decl-specifier-seq that lacks a type-specifier or that has a type-specifier that only specifies cv-qualifiers. The âimplicit intâ rule of C is no longer supported.")

[4](#general-4)

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

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

[*enum-specifier*](dcl.enum#nt:enum-specifier "9.8.1 Enumeration declarations [dcl.enum]")*s*,[*class-specifier*](class.pre#nt:class-specifier "11.1 Preamble [class.pre]")*s*,
and[*typename-specifier*](temp.res.general#nt:typename-specifier "13.8.1 General [temp.res.general]")*s* are discussed
in[[dcl.enum]](dcl.enum "9.8.1 Enumeration declarations"),[[class]](class "11 Classes"),
and[[temp.res]](temp.res "13.8 Name resolution"), respectively[.](#general-4.sentence-1)

The remaining[*type-specifier*](#nt:type-specifier "9.2.9.1 General [dcl.type.general]")*s* are discussed in the rest of [dcl.type][.](#general-4.sentence-2)

â *end note*]

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

There is no special
provision for a [*decl-specifier-seq*](dcl.spec.general#nt:decl-specifier-seq "9.2.1 General [dcl.spec.general]") that
lacks a [*type-specifier*](#nt:type-specifier "9.2.9.1 General [dcl.type.general]") or that has a[*type-specifier*](#nt:type-specifier "9.2.9.1 General [dcl.type.general]") that only specifies [*cv-qualifier*](dcl.decl.general#nt:cv-qualifier "9.3.1 General [dcl.decl.general]")*s*[.](#footnote-74.sentence-1)

The âimplicit intâ rule of C is no longer supported[.](#footnote-74.sentence-2)

#### [9.2.9.2](#cv) The *cv-qualifier**s* [[dcl.type.cv]](dcl.type.cv)

[1](#cv-1)

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

There are two [*cv-qualifier*](dcl.decl.general#nt:cv-qualifier "9.3.1 General [dcl.decl.general]")*s*, const andvolatile[.](#cv-1.sentence-1)

Each [*cv-qualifier*](dcl.decl.general#nt:cv-qualifier "9.3.1 General [dcl.decl.general]") shall appear at most once in
a [*cv-qualifier-seq*](dcl.decl.general#nt:cv-qualifier-seq "9.3.1 General [dcl.decl.general]")[.](#cv-1.sentence-2)

If a [*cv-qualifier*](dcl.decl.general#nt:cv-qualifier "9.3.1 General [dcl.decl.general]") appears in a[*decl-specifier-seq*](dcl.spec.general#nt:decl-specifier-seq "9.2.1 General [dcl.spec.general]"), the [*init-declarator-list*](dcl.decl.general#nt:init-declarator-list "9.3.1 General [dcl.decl.general]") or [*member-declarator-list*](class.mem.general#nt:member-declarator-list "11.4.1 General [class.mem.general]") of
the declaration shall not be empty[.](#cv-1.sentence-3)

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

[[basic.type.qualifier]](basic.type.qualifier "6.9.5 CV-qualifiers") and [[dcl.fct]](dcl.fct "9.3.4.6 Functions") describe how cv-qualifiers affect object and
function types[.](#cv-1.sentence-4)

â *end note*]

Redundant cv-qualifications are ignored[.](#cv-1.sentence-5)

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

For example,
these could be introduced by typedefs[.](#cv-1.sentence-6)

â *end note*]

[2](#cv-2)

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

[*Note [3](#cv-note-3)*:

Declaring a variable const can affect its linkage ([[dcl.stc]](dcl.stc "9.2.2 Storage class specifiers"))
and its usability in constant expressions ([[expr.const]](expr.const "7.7 Constant expressions"))[.](#cv-2.sentence-1)

As
described in [[dcl.init]](dcl.init "9.5 Initializers"), the definition of an object or subobject
of const-qualified type must specify an initializer or be subject to
default-initialization[.](#cv-2.sentence-2)

â *end note*]

[3](#cv-3)

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

A pointer or reference to a cv-qualified type need not actually point or
refer to a cv-qualified object, but it is treated as if it does; a
const-qualified access path cannot be used to modify an object even if
the object referenced is a non-const object and can be modified through
some other access path[.](#cv-3.sentence-1)

[*Note [4](#cv-note-4)*:

Cv-qualifiers are supported by the type system so that they cannot be
subverted without [casting](expr.const.cast "7.6.1.11 Const cast [expr.const.cast]")[.](#cv-3.sentence-2)

â *end note*]

[4](#cv-4)

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

Any attempt to modify ([[expr.assign]](expr.assign "7.6.19 Assignment and compound assignment operators"), [[expr.post.incr]](expr.post.incr "7.6.1.6 Increment and decrement"), [[expr.pre.incr]](expr.pre.incr "7.6.2.3 Increment and decrement")) a
const object ([[basic.type.qualifier]](basic.type.qualifier "6.9.5 CV-qualifiers")) during its
lifetime ([[basic.life]](basic.life "6.8.4 Lifetime")) results in undefined behavior[.](#cv-4.sentence-1)

[*Example [1](#cv-example-1)*: const int ci = 3; // cv-qualified (initialized as required) ci = 4; // error: attempt to modify constint i = 2; // not cv-qualifiedconst int* cip; // pointer to const int cip = &i; // OK, cv-qualified access path to unqualified*cip = 4; // error: attempt to modify through ptr to constint* ip;
ip = const_cast<int*>(cip); // cast needed to convert const int* to int**ip = 4; // defined: *ip points to i, a non-const objectconst int* ciq = new const int (3); // initialized as requiredint* iq = const_cast<int*>(ciq); // cast required*iq = 4; // undefined behavior: modifies a const object

For another example,struct X {mutable int i; int j;};struct Y { X x;
 Y();};

const Y y;
y.x.i++; // well-formed: mutable member can be modified y.x.j++; // error: const-qualified member modified Y* p = const_cast<Y*>(&y); // cast away const-ness of y p->x.i = 99; // well-formed: mutable member can be modified p->x.j = 99; // undefined behavior: modifies a const subobject

â *end example*]

[5](#cv-5)

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

The semantics of an access through a volatile glvalue areimplementation-defined[.](#cv-5.sentence-1)

If an attempt is made to access an object defined with a
volatile-qualified type through the use of a non-volatile glvalue,
the behavior is undefined[.](#cv-5.sentence-2)

[6](#cv-6)

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

[*Note [5](#cv-note-5)*:

volatile is a hint to the implementation to avoid aggressive
optimization involving the object because it is possible for the value of the object
to change by means undetectable by an implementation[.](#cv-6.sentence-1)

Furthermore, for some implementations, volatile can indicate that
special hardware instructions are needed to access the object[.](#cv-6.sentence-2)

See [[intro.execution]](intro.execution "6.10.1 Sequential execution") for detailed semantics[.](#cv-6.sentence-3)

In general, the
semantics of volatile are intended to be the same in C++ as
they are in C[.](#cv-6.sentence-4)

â *end note*]

#### [9.2.9.3](#simple) Simple type specifiers [[dcl.type.simple]](dcl.type.simple)

[1](#simple-1)

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

The simple type specifiers are

[simple-type-specifier:](#nt:simple-type-specifier "9.2.9.3 Simple type specifiers [dcl.type.simple]")  
[*nested-name-specifier*](expr.prim.id.qual#nt:nested-name-specifier "7.5.5.3 Qualified names [expr.prim.id.qual]")opt [*type-name*](#nt:type-name "9.2.9.3 Simple type specifiers [dcl.type.simple]")  
[*nested-name-specifier*](expr.prim.id.qual#nt:nested-name-specifier "7.5.5.3 Qualified names [expr.prim.id.qual]") template [*simple-template-id*](temp.names#nt:simple-template-id "13.3 Names of template specializations [temp.names]")  
[*computed-type-specifier*](#nt:computed-type-specifier "9.2.9.3 Simple type specifiers [dcl.type.simple]")  
[*placeholder-type-specifier*](#nt:placeholder-type-specifier "9.2.9.7.1 General [dcl.spec.auto.general]")  
[*nested-name-specifier*](expr.prim.id.qual#nt:nested-name-specifier "7.5.5.3 Qualified names [expr.prim.id.qual]")opt [*template-name*](temp.names#nt:template-name "13.3 Names of template specializations [temp.names]")  
char  
char8_t  
char16_t  
char32_t  
wchar_t  
bool  
short  
int  
long  
signed  
unsigned  
float  
double  
void

[type-name:](#nt:type-name "9.2.9.3 Simple type specifiers [dcl.type.simple]")  
[*class-name*](class.pre#nt:class-name "11.1 Preamble [class.pre]")  
[*enum-name*](dcl.enum#nt:enum-name "9.8.1 Enumeration declarations [dcl.enum]")  
[*typedef-name*](dcl.typedef#nt:typedef-name "9.2.4 The typedef specifier [dcl.typedef]")

[computed-type-specifier:](#nt:computed-type-specifier "9.2.9.3 Simple type specifiers [dcl.type.simple]")  
[*decltype-specifier*](#nt:decltype-specifier "9.2.9.6 Decltype specifiers [dcl.type.decltype]")  
[*pack-index-specifier*](#nt:pack-index-specifier "9.2.9.4 Pack indexing specifier [dcl.type.pack.index]")  
[*splice-type-specifier*](#nt:splice-type-specifier "9.2.9.9 Type splicing [dcl.type.splice]")

[2](#simple-2)

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

The component names of a [*simple-type-specifier*](#nt:simple-type-specifier "9.2.9.3 Simple type specifiers [dcl.type.simple]") 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]"),[*type-name*](#nt:type-name "9.2.9.3 Simple type specifiers [dcl.type.simple]"),[*simple-template-id*](temp.names#nt:simple-template-id "13.3 Names of template specializations [temp.names]"),[*template-name*](temp.names#nt:template-name "13.3 Names of template specializations [temp.names]"), and/or[*type-constraint*](temp.param#nt:type-constraint "13.2 Template parameters [temp.param]") (if it is a [*placeholder-type-specifier*](#nt:placeholder-type-specifier "9.2.9.7.1 General [dcl.spec.auto.general]"))[.](#simple-2.sentence-1)

The component name of a [*type-name*](#nt:type-name "9.2.9.3 Simple type specifiers [dcl.type.simple]") is the first name in it[.](#simple-2.sentence-2)

[3](#simple-3)

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

A [*placeholder-type-specifier*](#nt:placeholder-type-specifier "9.2.9.7.1 General [dcl.spec.auto.general]") is a placeholder for
a type to be deduced ([[dcl.spec.auto]](#dcl.spec.auto "9.2.9.7 Placeholder type specifiers"))[.](#simple-3.sentence-1)

A [*type-specifier*](#nt:type-specifier "9.2.9.1 General [dcl.type.general]") is a placeholder for
a deduced class type ([[dcl.type.class.deduct]](#class.deduct "9.2.9.8 Deduced class template specialization types")) if either

- [(3.1)](#simple-3.1)

it is of the formtypenameopt [*nested-name-specifier*](expr.prim.id.qual#nt:nested-name-specifier "7.5.5.3 Qualified names [expr.prim.id.qual]")opt [*template-name*](temp.names#nt:template-name "13.3 Names of template specializations [temp.names]") or

- [(3.2)](#simple-3.2)

it is of the form typenameopt [*splice-specifier*](basic.splice#nt:splice-specifier "6.6 Splice specifiers [basic.splice]") and
the [*splice-specifier*](basic.splice#nt:splice-specifier "6.6 Splice specifiers [basic.splice]") designates
a class template or alias template[.](#simple-3.sentence-2)

The [*nested-name-specifier*](expr.prim.id.qual#nt:nested-name-specifier "7.5.5.3 Qualified names [expr.prim.id.qual]") or [*splice-specifier*](basic.splice#nt:splice-specifier "6.6 Splice specifiers [basic.splice]"),
if any, shall be non-dependent and
the [*template-name*](temp.names#nt:template-name "13.3 Names of template specializations [temp.names]") or [*splice-specifier*](basic.splice#nt:splice-specifier "6.6 Splice specifiers [basic.splice]") shall designate a deducible template[.](#simple-3.sentence-3)

A [*deducible template*](#def:template,deducible "9.2.9.3 Simple type specifiers [dcl.type.simple]") is either a class template or
is an alias template whose [*defining-type-id*](dcl.name#nt:defining-type-id "9.3.2 Type names [dcl.name]") is of the form

typenameopt [*nested-name-specifier*](expr.prim.id.qual#nt:nested-name-specifier "7.5.5.3 Qualified names [expr.prim.id.qual]")opt templateopt [*simple-template-id*](temp.names#nt:simple-template-id "13.3 Names of template specializations [temp.names]")

where the [*nested-name-specifier*](expr.prim.id.qual#nt:nested-name-specifier "7.5.5.3 Qualified names [expr.prim.id.qual]") (if any) is non-dependent and
the [*template-name*](temp.names#nt:template-name "13.3 Names of template specializations [temp.names]") of the [*simple-template-id*](temp.names#nt:simple-template-id "13.3 Names of template specializations [temp.names]") names a deducible template[.](#simple-3.sentence-5)

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

An injected-class-name is never interpreted as a [*template-name*](temp.names#nt:template-name "13.3 Names of template specializations [temp.names]") in contexts where class template argument deduction would be performed ([[temp.local]](temp.local "13.8.2 Locally declared names"))[.](#simple-3.sentence-6)

â *end note*]

The other[*simple-type-specifier*](#nt:simple-type-specifier "9.2.9.3 Simple type specifiers [dcl.type.simple]")*s* specify either a previously-declared type, a type determined from an
expression, or one of the
fundamental types ([[basic.fundamental]](basic.fundamental "6.9.2 Fundamental types"))[.](#simple-3.sentence-7)

Table [17](#tab:dcl.type.simple "Table 17: simple-type-specifiers and the types they specify") summarizes the valid combinations of[*simple-type-specifier*](#nt:simple-type-specifier "9.2.9.3 Simple type specifiers [dcl.type.simple]")*s* and the types they specify[.](#simple-3.sentence-8)

Table [17](#tab:dcl.type.simple) — [*simple-type-specifier*](#nt:simple-type-specifier "9.2.9.3 Simple type specifiers [dcl.type.simple]")*s* and the types they specify [[tab:dcl.type.simple]](./tab:dcl.type.simple)  

| [ð](#tab:dcl.type.simple-row-1)<br>**Specifier(s)** | **Type** |
| --- | --- |
| [ð](#tab:dcl.type.simple-row-2)<br>[*type-name*](#nt:type-name "9.2.9.3 Simple type specifiers [dcl.type.simple]") | the type named |
| [ð](#tab:dcl.type.simple-row-3)<br>[*simple-template-id*](temp.names#nt:simple-template-id "13.3 Names of template specializations [temp.names]") | the type as defined in [[temp.names]](temp.names "13.3 Names of template specializations") |
| [ð](#tab:dcl.type.simple-row-4)<br>[*decltype-specifier*](#nt:decltype-specifier "9.2.9.6 Decltype specifiers [dcl.type.decltype]") | the type as defined in [[dcl.type.decltype]](#decltype "9.2.9.6 Decltype specifiers") |
| [ð](#tab:dcl.type.simple-row-5)<br>[*pack-index-specifier*](#nt:pack-index-specifier "9.2.9.4 Pack indexing specifier [dcl.type.pack.index]") | the type as defined in [[dcl.type.pack.index]](#pack.index "9.2.9.4 Pack indexing specifier") |
| [ð](#tab:dcl.type.simple-row-6)<br>[*placeholder-type-specifier*](#nt:placeholder-type-specifier "9.2.9.7.1 General [dcl.spec.auto.general]") | the type as defined in [[dcl.spec.auto]](#dcl.spec.auto "9.2.9.7 Placeholder type specifiers") |
| [ð](#tab:dcl.type.simple-row-7)<br>[*template-name*](temp.names#nt:template-name "13.3 Names of template specializations [temp.names]") | the type as defined in [[dcl.type.class.deduct]](#class.deduct "9.2.9.8 Deduced class template specialization types") |
| [ð](#tab:dcl.type.simple-row-8)<br>[*splice-type-specifier*](#nt:splice-type-specifier "9.2.9.9 Type splicing [dcl.type.splice]") | the type as defined in [[dcl.type.splice]](#splice "9.2.9.9 Type splicing") |
| [ð](#tab:dcl.type.simple-row-9)<br>char | âcharâ |
| [ð](#tab:dcl.type.simple-row-10)<br>unsigned char | âunsigned charâ |
| [ð](#tab:dcl.type.simple-row-11)<br>signed char | âsigned charâ |
| [ð](#tab:dcl.type.simple-row-12)<br>char8_t | âchar8_tâ |
| [ð](#tab:dcl.type.simple-row-13)<br>char16_t | âchar16_tâ |
| [ð](#tab:dcl.type.simple-row-14)<br>char32_t | âchar32_tâ |
| [ð](#tab:dcl.type.simple-row-15)<br>bool | âboolâ |
| [ð](#tab:dcl.type.simple-row-16)<br>unsigned | âunsigned intâ |
| [ð](#tab:dcl.type.simple-row-17)<br>unsigned int | âunsigned intâ |
| [ð](#tab:dcl.type.simple-row-18)<br>signed | âintâ |
| [ð](#tab:dcl.type.simple-row-19)<br>signed int | âintâ |
| [ð](#tab:dcl.type.simple-row-20)<br>int | âintâ |
| [ð](#tab:dcl.type.simple-row-21)<br>unsigned short int | âunsigned short intâ |
| [ð](#tab:dcl.type.simple-row-22)<br>unsigned short | âunsigned short intâ |
| [ð](#tab:dcl.type.simple-row-23)<br>unsigned long int | âunsigned long intâ |
| [ð](#tab:dcl.type.simple-row-24)<br>unsigned long | âunsigned long intâ |
| [ð](#tab:dcl.type.simple-row-25)<br>unsigned long long int | âunsigned long long intâ |
| [ð](#tab:dcl.type.simple-row-26)<br>unsigned long long | âunsigned long long intâ |
| [ð](#tab:dcl.type.simple-row-27)<br>signed long int | âlong intâ |
| [ð](#tab:dcl.type.simple-row-28)<br>signed long | âlong intâ |
| [ð](#tab:dcl.type.simple-row-29)<br>signed long long int | âlong long intâ |
| [ð](#tab:dcl.type.simple-row-30)<br>signed long long | âlong long intâ |
| [ð](#tab:dcl.type.simple-row-31)<br>long long int | âlong long intâ |
| [ð](#tab:dcl.type.simple-row-32)<br>long long | âlong long intâ |
| [ð](#tab:dcl.type.simple-row-33)<br>long int | âlong intâ |
| [ð](#tab:dcl.type.simple-row-34)<br>long | âlong intâ |
| [ð](#tab:dcl.type.simple-row-35)<br>signed short int | âshort intâ |
| [ð](#tab:dcl.type.simple-row-36)<br>signed short | âshort intâ |
| [ð](#tab:dcl.type.simple-row-37)<br>short int | âshort intâ |
| [ð](#tab:dcl.type.simple-row-38)<br>short | âshort intâ |
| [ð](#tab:dcl.type.simple-row-39)<br>wchar_t | âwchar_tâ |
| [ð](#tab:dcl.type.simple-row-40)<br>float | âfloatâ |
| [ð](#tab:dcl.type.simple-row-41)<br>double | âdoubleâ |
| [ð](#tab:dcl.type.simple-row-42)<br>long double | âlong doubleâ |
| [ð](#tab:dcl.type.simple-row-43)<br>void | âvoidâ |

[4](#simple-4)

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

When multiple [*simple-type-specifier*](#nt:simple-type-specifier "9.2.9.3 Simple type specifiers [dcl.type.simple]")*s* are allowed, they can be
freely intermixed with other [*decl-specifier*](dcl.spec.general#nt:decl-specifier "9.2.1 General [dcl.spec.general]")*s* in any order[.](#simple-4.sentence-1)

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

It is implementation-defined whether objects of char type are
represented as signed or unsigned quantities[.](#simple-4.sentence-2)

The signed specifier
forces char objects to be signed; it is redundant in other contexts[.](#simple-4.sentence-3)

â *end note*]

#### [9.2.9.4](#pack.index) Pack indexing specifier [[dcl.type.pack.index]](dcl.type.pack.index)

[pack-index-specifier:](#nt:pack-index-specifier "9.2.9.4 Pack indexing specifier [dcl.type.pack.index]")  
[*typedef-name*](dcl.typedef#nt:typedef-name "9.2.4 The typedef specifier [dcl.typedef]") ... [ [*constant-expression*](expr.const#nt:constant-expression "7.7 Constant expressions [expr.const]") ]

[1](#pack.index-1)

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

The [*typedef-name*](dcl.typedef#nt:typedef-name "9.2.4 The typedef specifier [dcl.typedef]") P in a [*pack-index-specifier*](#nt:pack-index-specifier "9.2.9.4 Pack indexing specifier [dcl.type.pack.index]") shall denote a pack[.](#pack.index-1.sentence-1)

[2](#pack.index-2)

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

The [*constant-expression*](expr.const#nt:constant-expression "7.7 Constant expressions [expr.const]") shall be
a converted constant expression ([[expr.const]](expr.const "7.7 Constant expressions")) of type std​::​size_t whose value V, termed the index,
is such that 0â¤V<sizeof...(P)[.](#pack.index-2.sentence-1)

[3](#pack.index-3)

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

A [*pack-index-specifier*](#nt:pack-index-specifier "9.2.9.4 Pack indexing specifier [dcl.type.pack.index]") is a pack expansion ([[temp.variadic]](temp.variadic "13.7.4 Variadic templates"))[.](#pack.index-3.sentence-1)

[4](#pack.index-4)

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

[*Note [1](#pack.index-note-1)*:

The [*pack-index-specifier*](#nt:pack-index-specifier "9.2.9.4 Pack indexing specifier [dcl.type.pack.index]") denotes
the type of the Vth element of the pack[.](#pack.index-4.sentence-1)

â *end note*]

#### [9.2.9.5](#elab) Elaborated type specifiers [[dcl.type.elab]](dcl.type.elab)

[elaborated-type-specifier:](#nt:elaborated-type-specifier "9.2.9.5 Elaborated type specifiers [dcl.type.elab]")  
[*class-key*](class.pre#nt:class-key "11.1 Preamble [class.pre]") [*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]")opt [*identifier*](lex.name#nt:identifier "5.11 Identifiers [lex.name]")  
[*class-key*](class.pre#nt:class-key "11.1 Preamble [class.pre]") [*simple-template-id*](temp.names#nt:simple-template-id "13.3 Names of template specializations [temp.names]")  
[*class-key*](class.pre#nt:class-key "11.1 Preamble [class.pre]") [*nested-name-specifier*](expr.prim.id.qual#nt:nested-name-specifier "7.5.5.3 Qualified names [expr.prim.id.qual]") templateopt [*simple-template-id*](temp.names#nt:simple-template-id "13.3 Names of template specializations [temp.names]")  
enum [*nested-name-specifier*](expr.prim.id.qual#nt:nested-name-specifier "7.5.5.3 Qualified names [expr.prim.id.qual]")opt [*identifier*](lex.name#nt:identifier "5.11 Identifiers [lex.name]")

[1](#elab-1)

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

The component names of an [*elaborated-type-specifier*](#nt:elaborated-type-specifier "9.2.9.5 Elaborated type specifiers [dcl.type.elab]") are
its [*identifier*](lex.name#nt:identifier "5.11 Identifiers [lex.name]") (if any) and
those of its [*nested-name-specifier*](expr.prim.id.qual#nt:nested-name-specifier "7.5.5.3 Qualified names [expr.prim.id.qual]") and[*simple-template-id*](temp.names#nt:simple-template-id "13.3 Names of template specializations [temp.names]") (if any)[.](#elab-1.sentence-1)

[2](#elab-2)

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

If an [*elaborated-type-specifier*](#nt:elaborated-type-specifier "9.2.9.5 Elaborated type specifiers [dcl.type.elab]") is the sole constituent of a
declaration, the declaration is ill-formed unless it is an explicit
specialization ([[temp.expl.spec]](temp.expl.spec "13.9.4 Explicit specialization")),
a partial specialization ([[temp.spec.partial]](temp.spec.partial "13.7.6 Partial specialization")),
an explicit
instantiation ([[temp.explicit]](temp.explicit "13.9.3 Explicit instantiation")), or it has one of the following
forms:

[*class-key*](class.pre#nt:class-key "11.1 Preamble [class.pre]") [*attribute-specifier-seq*](dcl.attr.grammar#nt:attribute-specifier-seq "9.13.1 Attribute syntax and semantics [dcl.attr.grammar]")opt [*identifier*](lex.name#nt:identifier "5.11 Identifiers [lex.name]") ;  
[*class-key*](class.pre#nt:class-key "11.1 Preamble [class.pre]") [*attribute-specifier-seq*](dcl.attr.grammar#nt:attribute-specifier-seq "9.13.1 Attribute syntax and semantics [dcl.attr.grammar]")opt [*simple-template-id*](temp.names#nt:simple-template-id "13.3 Names of template specializations [temp.names]") ;

In the first case,
the [*elaborated-type-specifier*](#nt:elaborated-type-specifier "9.2.9.5 Elaborated type specifiers [dcl.type.elab]") declares
the [*identifier*](lex.name#nt:identifier "5.11 Identifiers [lex.name]") as a [*class-name*](class.pre#nt:class-name "11.1 Preamble [class.pre]")[.](#elab-2.sentence-2)

The second case shall appear only
in an [*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
in a [*template-declaration*](temp.pre#nt:template-declaration "13.1 Preamble [temp.pre]") (where it declares a partial specialization)[.](#elab-2.sentence-3)

The [*attribute-specifier-seq*](dcl.attr.grammar#nt:attribute-specifier-seq "9.13.1 Attribute syntax and semantics [dcl.attr.grammar]"), if any, appertains
to the class or template being declared[.](#elab-2.sentence-4)

[3](#elab-3)

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

Otherwise, an [*elaborated-type-specifier*](#nt:elaborated-type-specifier "9.2.9.5 Elaborated type specifiers [dcl.type.elab]") E shall not have
an [*attribute-specifier-seq*](dcl.attr.grammar#nt:attribute-specifier-seq "9.13.1 Attribute syntax and semantics [dcl.attr.grammar]")[.](#elab-3.sentence-1)

If E contains an [*identifier*](lex.name#nt:identifier "5.11 Identifiers [lex.name]") but no [*nested-name-specifier*](expr.prim.id.qual#nt:nested-name-specifier "7.5.5.3 Qualified names [expr.prim.id.qual]") and
(unqualified) lookup for the [*identifier*](lex.name#nt:identifier "5.11 Identifiers [lex.name]") finds nothing,E shall not be introduced by the enum keyword and
declares the [*identifier*](lex.name#nt:identifier "5.11 Identifiers [lex.name]") as a [*class-name*](class.pre#nt:class-name "11.1 Preamble [class.pre]")[.](#elab-3.sentence-2)

The target scope of E is the nearest enclosing namespace or block scope[.](#elab-3.sentence-3)

[4](#elab-4)

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

A [*friend-type-specifier*](class.mem.general#nt:friend-type-specifier "11.4.1 General [class.mem.general]") that is an [*elaborated-type-specifier*](#nt:elaborated-type-specifier "9.2.9.5 Elaborated type specifiers [dcl.type.elab]") shall have one of the following forms:

[*class-key*](class.pre#nt:class-key "11.1 Preamble [class.pre]") [*nested-name-specifier*](expr.prim.id.qual#nt:nested-name-specifier "7.5.5.3 Qualified names [expr.prim.id.qual]")opt [*identifier*](lex.name#nt:identifier "5.11 Identifiers [lex.name]")  
[*class-key*](class.pre#nt:class-key "11.1 Preamble [class.pre]") [*simple-template-id*](temp.names#nt:simple-template-id "13.3 Names of template specializations [temp.names]")  
[*class-key*](class.pre#nt:class-key "11.1 Preamble [class.pre]") [*nested-name-specifier*](expr.prim.id.qual#nt:nested-name-specifier "7.5.5.3 Qualified names [expr.prim.id.qual]") templateopt [*simple-template-id*](temp.names#nt:simple-template-id "13.3 Names of template specializations [temp.names]")

Any unqualified lookup for the [*identifier*](lex.name#nt:identifier "5.11 Identifiers [lex.name]") (in the first case)
does not consider scopes that contain
the nearest enclosing namespace or block scope; no name is bound[.](#elab-4.sentence-1)

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

A [*using-directive*](namespace.udir#nt:using-directive "9.9.4 Using namespace directive [namespace.udir]") in the target scope is ignored
if it refers to a namespace not contained by that scope[.](#elab-4.sentence-2)

â *end note*]

[5](#elab-5)

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

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

[[basic.lookup.elab]](basic.lookup.elab "6.5.6 Elaborated type specifiers") describes how name lookup proceeds
in an [*elaborated-type-specifier*](#nt:elaborated-type-specifier "9.2.9.5 Elaborated type specifiers [dcl.type.elab]")[.](#elab-5.sentence-1)

An [*elaborated-type-specifier*](#nt:elaborated-type-specifier "9.2.9.5 Elaborated type specifiers [dcl.type.elab]") can be used to refer to
a previously declared [*class-name*](class.pre#nt:class-name "11.1 Preamble [class.pre]") or [*enum-name*](dcl.enum#nt:enum-name "9.8.1 Enumeration declarations [dcl.enum]") even if the name has been hidden by a non-type declaration[.](#elab-5.sentence-2)

â *end note*]

[6](#elab-6)

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

If the [*identifier*](lex.name#nt:identifier "5.11 Identifiers [lex.name]") or [*simple-template-id*](temp.names#nt:simple-template-id "13.3 Names of template specializations [temp.names]") in an [*elaborated-type-specifier*](#nt:elaborated-type-specifier "9.2.9.5 Elaborated type specifiers [dcl.type.elab]") resolves to a [*class-name*](class.pre#nt:class-name "11.1 Preamble [class.pre]") or[*enum-name*](dcl.enum#nt:enum-name "9.8.1 Enumeration declarations [dcl.enum]"), the [*elaborated-type-specifier*](#nt:elaborated-type-specifier "9.2.9.5 Elaborated type specifiers [dcl.type.elab]") introduces it into the declaration the same way a[*simple-type-specifier*](#nt:simple-type-specifier "9.2.9.3 Simple type specifiers [dcl.type.simple]") introduces
its [*type-name*](#nt:type-name "9.2.9.3 Simple type specifiers [dcl.type.simple]") ([[dcl.type.simple]](#simple "9.2.9.3 Simple type specifiers"))[.](#elab-6.sentence-1)

If the [*identifier*](lex.name#nt:identifier "5.11 Identifiers [lex.name]") or [*simple-template-id*](temp.names#nt:simple-template-id "13.3 Names of template specializations [temp.names]") resolves to 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.names]](temp.names "13.3 Names of template specializations")),
the [*elaborated-type-specifier*](#nt:elaborated-type-specifier "9.2.9.5 Elaborated type specifiers [dcl.type.elab]") is ill-formed[.](#elab-6.sentence-2)

[*Note [3](#elab-note-3)*:

This implies that, within a class template with a template[*type-parameter*](temp.param#nt:type-parameter "13.2 Template parameters [temp.param]") T, the declarationfriend class T; is ill-formed[.](#elab-6.sentence-3)

However, the similar declaration friend T; is well-formed ([[class.friend]](class.friend "11.8.4 Friends"))[.](#elab-6.sentence-4)

â *end note*]

[7](#elab-7)

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

The [*class-key*](class.pre#nt:class-key "11.1 Preamble [class.pre]") or enum keyword
present in an[*elaborated-type-specifier*](#nt:elaborated-type-specifier "9.2.9.5 Elaborated type specifiers [dcl.type.elab]") shall agree in kind with the
declaration to which the name in the[*elaborated-type-specifier*](#nt:elaborated-type-specifier "9.2.9.5 Elaborated type specifiers [dcl.type.elab]") refers[.](#elab-7.sentence-1)

This rule also applies to
the form of [*elaborated-type-specifier*](#nt:elaborated-type-specifier "9.2.9.5 Elaborated type specifiers [dcl.type.elab]") that declares a[*class-name*](class.pre#nt:class-name "11.1 Preamble [class.pre]") or friend class since it can be construed
as referring to the definition of the class[.](#elab-7.sentence-2)

Thus, in any[*elaborated-type-specifier*](#nt:elaborated-type-specifier "9.2.9.5 Elaborated type specifiers [dcl.type.elab]"), the enum keyword
shall be
used to refer to an enumeration ([[dcl.enum]](dcl.enum "9.8.1 Enumeration declarations")), the union[*class-key*](class.pre#nt:class-key "11.1 Preamble [class.pre]") shall be used to refer to a union ([[class.union]](class.union "11.5 Unions")),
and either the class or struct[*class-key*](class.pre#nt:class-key "11.1 Preamble [class.pre]") shall be used to refer to a non-union class ([[class.pre]](class.pre "11.1 Preamble"))[.](#elab-7.sentence-3)

[*Example [1](#elab-example-1)*: enum class E { a, b };enum E x = E::a; // OKstruct S { } s;class S* p = &s; // OK â *end example*]

#### [9.2.9.6](#decltype) Decltype specifiers [[dcl.type.decltype]](dcl.type.decltype)

[decltype-specifier:](#nt:decltype-specifier "9.2.9.6 Decltype specifiers [dcl.type.decltype]")  
decltype ( [*expression*](expr.comma#nt:expression "7.6.20 Comma operator [expr.comma]") )

[1](#decltype-1)

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

For an expression E, the type denoted by decltype(E) is defined as follows:

- [(1.1)](#decltype-1.1)

  if E is an unparenthesized [*id-expression*](expr.prim.id.general#nt:id-expression "7.5.5.1 General [expr.prim.id.general]") naming a structured binding ([[dcl.struct.bind]](dcl.struct.bind "9.7 Structured binding declarations")),decltype(E) is the referenced type as given in
the specification of the structured binding declaration;

- [(1.2)](#decltype-1.2)

  otherwise, if E is an unparenthesized [*id-expression*](expr.prim.id.general#nt:id-expression "7.5.5.1 General [expr.prim.id.general]") naming a constant template parameter ([[temp.param]](temp.param "13.2 Template parameters")),decltype(E) is the type of the template parameter
after performing any necessary
type deduction ([[dcl.spec.auto]](#dcl.spec.auto "9.2.9.7 Placeholder type specifiers"), [[dcl.type.class.deduct]](#class.deduct "9.2.9.8 Deduced class template specialization types"));

- [(1.3)](#decltype-1.3)

  otherwise, if E is an unparenthesized [*id-expression*](expr.prim.id.general#nt:id-expression "7.5.5.1 General [expr.prim.id.general]") or
an unparenthesized
class
member access ([[expr.ref]](expr.ref "7.6.1.5 Class member access")), decltype(E) is the
type of the entity named by E[.](#decltype-1.3.sentence-1)
  If there is no such entity, the program is ill-formed;

- [(1.4)](#decltype-1.4)

  otherwise, if E is an unparenthesized [*splice-expression*](expr.prim.splice#nt:splice-expression "7.5.9 Expression splicing [expr.prim.splice]"),decltype(E) is the type of the entity, object, or value
designated by the [*splice-specifier*](basic.splice#nt:splice-specifier "6.6 Splice specifiers [basic.splice]") of E;

- [(1.5)](#decltype-1.5)

  otherwise, if E is
an xvalue, decltype(E) is T&&, where T is the type
of E;

- [(1.6)](#decltype-1.6)

  otherwise, if E is an lvalue, decltype(E) is T&, where T is the type of E;

- [(1.7)](#decltype-1.7)

  otherwise, decltype(E) is the type of E[.](#decltype-1.7.sentence-1)

The operand of the decltype specifier is an [unevaluated operand](expr.context#def:unevaluated_operand "7.2.3 Context dependence [expr.context]")[.](#decltype-1.sentence-2)

[*Example [1](#decltype-example-1)*: const int&& foo();int i;struct A { double x; };const A* a = new A();decltype(foo()) x1 = 17; // type is const int&&decltype(i) x2; // type is intdecltype(a->x) x3; // type is doubledecltype((a->x)) x4 = x3; // type is const double&decltype([:^^x1:]) x5 = 18; // type is const int&&decltype(([:^^x1:])) x6 = 19; // type is const int&void f() {[](auto ...pack) {decltype(pack...[0]) x7; // type is intdecltype((pack...[0])) x8; // type is int&}(0);} â *end example*]

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

The rules for determining types involving decltype(auto) are specified
in [[dcl.spec.auto]](#dcl.spec.auto "9.2.9.7 Placeholder type specifiers")[.](#decltype-1.sentence-3)

â *end note*]

[2](#decltype-2)

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

If the operand of a [*decltype-specifier*](#nt:decltype-specifier "9.2.9.6 Decltype specifiers [dcl.type.decltype]") is a prvalue
and is not a (possibly parenthesized) immediate invocation ([[expr.const]](expr.const "7.7 Constant expressions")),
the temporary materialization conversion is not applied ([[conv.rval]](conv.rval "7.3.5 Temporary materialization conversion"))
and no result object is provided for the prvalue[.](#decltype-2.sentence-1)

The type of the prvalue may be incomplete or an abstract class type[.](#decltype-2.sentence-2)

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

As a result, storage is not allocated for the prvalue and it is not destroyed[.](#decltype-2.sentence-3)

Thus, a class type is not instantiated
as a result of being the type of a function call in this context[.](#decltype-2.sentence-4)

In this context, the common purpose of
writing the expression is merely to refer to its type[.](#decltype-2.sentence-5)

In that sense, a[*decltype-specifier*](#nt:decltype-specifier "9.2.9.6 Decltype specifiers [dcl.type.decltype]") is analogous to a use of a [*typedef-name*](dcl.typedef#nt:typedef-name "9.2.4 The typedef specifier [dcl.typedef]"),
so the usual reasons for requiring a complete type do not apply[.](#decltype-2.sentence-6)

In particular,
it is not necessary to allocate storage for a temporary object or to enforce the
semantic constraints associated with invoking the type's destructor[.](#decltype-2.sentence-7)

â *end note*]

[*Note [3](#decltype-note-3)*:

Unlike the preceding rule, parentheses have no special meaning in this context[.](#decltype-2.sentence-8)

â *end note*]

[*Example [2](#decltype-example-2)*: template<class T> struct A { ~A() = delete; };template<class T> auto h()-> A<T>;template<class T> auto i(T) // identity-> T;template<class T> auto f(T) // #1-> decltype(i(h<T>())); // forces completion of A<T> and implicitly uses A<T>​::​~A()// for the temporary introduced by the use of h().// (A temporary is not introduced as a result of the use of i().)template<class T> auto f(T) // #2-> void;auto g() -> void { f(42); // OK, calls #2. (#1 is not a viable candidate: type deduction// fails ([[temp.deduct]](temp.deduct "13.10.3 Template argument deduction")) because A<int>​::​~A() is implicitly used in its// [*decltype-specifier*](#nt:decltype-specifier "9.2.9.6 Decltype specifiers [dcl.type.decltype]"))}template<class T> auto q(T)-> decltype((h<T>())); // does not force completion of A<T>; A<T>​::​~A() is not implicitly// used within the context of this [*decltype-specifier*](#nt:decltype-specifier "9.2.9.6 Decltype specifiers [dcl.type.decltype]")void r() { q(42); // error: deduction against q succeeds, so overload resolution selects// the specialization âq(T) -> decltype((h<T>()))'' with T=int;// the return type is A<int>, so a temporary is introduced and its// destructor is used, so the program is ill-formed} â *end example*]

#### [9.2.9.7](#dcl.spec.auto) Placeholder type specifiers [[dcl.spec.auto]](dcl.spec.auto)

#### [9.2.9.7.1](#dcl.spec.auto.general) General [[dcl.spec.auto.general]](dcl.spec.auto.general)

[placeholder-type-specifier:](#nt:placeholder-type-specifier "9.2.9.7.1 General [dcl.spec.auto.general]")  
[*type-constraint*](temp.param#nt:type-constraint "13.2 Template parameters [temp.param]")opt auto  
[*type-constraint*](temp.param#nt:type-constraint "13.2 Template parameters [temp.param]")opt decltype ( auto )

[1](#dcl.spec.auto.general-1)

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

A [*placeholder-type-specifier*](#nt:placeholder-type-specifier "9.2.9.7.1 General [dcl.spec.auto.general]") designates a placeholder type that will be replaced later,
typically by deduction
from an initializer[.](#dcl.spec.auto.general-1.sentence-1)

[2](#dcl.spec.auto.general-2)

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

The type of a [*parameter-declaration*](dcl.fct#nt:parameter-declaration "9.3.4.6 Functions [dcl.fct]") of a

- [(2.1)](#dcl.spec.auto.general-2.1)

function declaration ([[dcl.fct]](dcl.fct "9.3.4.6 Functions")),

- [(2.2)](#dcl.spec.auto.general-2.2)

[*lambda-expression*](expr.prim.lambda.general#nt:lambda-expression "7.5.6.1 General [expr.prim.lambda.general]") ([[expr.prim.lambda]](expr.prim.lambda "7.5.6 Lambda expressions")), or

- [(2.3)](#dcl.spec.auto.general-2.3)

[*template-parameter*](temp.param#nt:template-parameter "13.2 Template parameters [temp.param]") ([[temp.param]](temp.param "13.2 Template parameters"))

can be declared using
a [*placeholder-type-specifier*](#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]")opt auto[.](#dcl.spec.auto.general-2.sentence-1)

The placeholder type shall appear
as one of the [*decl-specifier*](dcl.spec.general#nt:decl-specifier "9.2.1 General [dcl.spec.general]")*s* in
the [*decl-specifier-seq*](dcl.spec.general#nt:decl-specifier-seq "9.2.1 General [dcl.spec.general]") or
as one of the [*type-specifier*](#nt:type-specifier "9.2.9.1 General [dcl.type.general]")*s* in
a [*trailing-return-type*](dcl.decl.general#nt:trailing-return-type "9.3.1 General [dcl.decl.general]") that specifies the type that replaces such
a [*decl-specifier*](dcl.spec.general#nt:decl-specifier "9.2.1 General [dcl.spec.general]") (see below);
the placeholder type
is a [*generic parameter type placeholder*](#def:generic_parameter_type_placeholder "9.2.9.7.1 General [dcl.spec.auto.general]") of the
function declaration,[*lambda-expression*](expr.prim.lambda.general#nt:lambda-expression "7.5.6.1 General [expr.prim.lambda.general]"), or[*template-parameter*](temp.param#nt:template-parameter "13.2 Template parameters [temp.param]"), respectively[.](#dcl.spec.auto.general-2.sentence-2)

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

Having a generic parameter type placeholder
signifies that the function is
an abbreviated function template ([[dcl.fct]](dcl.fct "9.3.4.6 Functions")) or
the lambda is a generic lambda ([[expr.prim.lambda]](expr.prim.lambda "7.5.6 Lambda expressions"))[.](#dcl.spec.auto.general-2.sentence-3)

â *end note*]

[3](#dcl.spec.auto.general-3)

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

A placeholder type can appear in
the [*decl-specifier-seq*](dcl.spec.general#nt:decl-specifier-seq "9.2.1 General [dcl.spec.general]") for a function declarator
that includes a [*trailing-return-type*](dcl.decl.general#nt:trailing-return-type "9.3.1 General [dcl.decl.general]") ([[dcl.fct]](dcl.fct "9.3.4.6 Functions"))[.](#dcl.spec.auto.general-3.sentence-1)

[4](#dcl.spec.auto.general-4)

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

A placeholder type can appear in
the [*decl-specifier-seq*](dcl.spec.general#nt:decl-specifier-seq "9.2.1 General [dcl.spec.general]") or [*type-specifier-seq*](#nt:type-specifier-seq "9.2.9.1 General [dcl.type.general]") in the declared return type of a function declarator that declares a function;
the return type of the function is
deduced from non-discarded return statements, if any, in the body
of the function ([[stmt.if]](stmt.if "8.5.2 The if statement"))[.](#dcl.spec.auto.general-4.sentence-1)

[5](#dcl.spec.auto.general-5)

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

The type of a variable declared using a placeholder type is
deduced from its initializer[.](#dcl.spec.auto.general-5.sentence-1)

This use is allowed
in an initializing declaration ([[dcl.init]](dcl.init "9.5 Initializers")) of a variable[.](#dcl.spec.auto.general-5.sentence-2)

The placeholder type shall appear as one of the[*decl-specifier*](dcl.spec.general#nt:decl-specifier "9.2.1 General [dcl.spec.general]")*s* in the [*decl-specifier-seq*](dcl.spec.general#nt:decl-specifier-seq "9.2.1 General [dcl.spec.general]") or as one of the[*type-specifier*](#nt:type-specifier "9.2.9.1 General [dcl.type.general]")*s* in a [*trailing-return-type*](dcl.decl.general#nt:trailing-return-type "9.3.1 General [dcl.decl.general]") that specifies the type that replaces such a [*decl-specifier*](dcl.spec.general#nt:decl-specifier "9.2.1 General [dcl.spec.general]");
the [*decl-specifier-seq*](dcl.spec.general#nt:decl-specifier-seq "9.2.1 General [dcl.spec.general]") shall be followed by one or more[*declarator*](dcl.decl.general#nt:declarator "9.3.1 General [dcl.decl.general]")*s*,
each of which shall
be followed by a non-empty[*initializer*](dcl.init.general#nt:initializer "9.5.1 General [dcl.init.general]")[.](#dcl.spec.auto.general-5.sentence-3)

[*Example [1](#dcl.spec.auto.general-example-1)*: auto x = 5; // OK, x has type intconst auto *v = &x, u = 6; // OK, v has type const int*, u has type const intstatic auto y = 0.0; // OK, y has type doubleauto int r; // error: auto is not a [*storage-class-specifier*](dcl.stc#nt:storage-class-specifier "9.2.2 Storage class specifiers [dcl.stc]")auto f() -> int; // OK, f returns intauto g() { return 0.0; } // OK, g returns doubleauto (*fp)() -> auto = f; // OKauto h(); // OK, h's return type will be deduced when it is defined â *end example*]

The auto [*type-specifier*](#nt:type-specifier "9.2.9.1 General [dcl.type.general]") can also be used to introduce
a structured binding declaration ([[dcl.struct.bind]](dcl.struct.bind "9.7 Structured binding declarations"))[.](#dcl.spec.auto.general-5.sentence-4)

[6](#dcl.spec.auto.general-6)

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

A placeholder type can also be used
in the [*type-specifier-seq*](#nt:type-specifier-seq "9.2.9.1 General [dcl.type.general]") of
the [*new-type-id*](expr.new#nt:new-type-id "7.6.2.8 New [expr.new]") or
in the [*type-id*](dcl.name#nt:type-id "9.3.2 Type names [dcl.name]") of a[*new-expression*](expr.new#nt:new-expression "7.6.2.8 New [expr.new]") ([[expr.new]](expr.new "7.6.2.8 New"))[.](#dcl.spec.auto.general-6.sentence-1)

In such a [*type-id*](dcl.name#nt:type-id "9.3.2 Type names [dcl.name]"),
the placeholder type shall appear
as one of the [*type-specifier*](#nt:type-specifier "9.2.9.1 General [dcl.type.general]")*s* in
the [*type-specifier-seq*](#nt:type-specifier-seq "9.2.9.1 General [dcl.type.general]") or
as one of the [*type-specifier*](#nt:type-specifier "9.2.9.1 General [dcl.type.general]")*s* in
a [*trailing-return-type*](dcl.decl.general#nt:trailing-return-type "9.3.1 General [dcl.decl.general]") that specifies the type that replaces such a [*type-specifier*](#nt:type-specifier "9.2.9.1 General [dcl.type.general]")[.](#dcl.spec.auto.general-6.sentence-2)

[7](#dcl.spec.auto.general-7)

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

The auto [*type-specifier*](#nt:type-specifier "9.2.9.1 General [dcl.type.general]") can also be used
as the [*simple-type-specifier*](#nt:simple-type-specifier "9.2.9.3 Simple type specifiers [dcl.type.simple]") in an explicit type conversion (functional notation) ([[expr.type.conv]](expr.type.conv "7.6.1.4 Explicit type conversion (functional notation)"))[.](#dcl.spec.auto.general-7.sentence-1)

[8](#dcl.spec.auto.general-8)

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

A program that uses a placeholder type in a context not
explicitly allowed in [[dcl.spec.auto]](#dcl.spec.auto "9.2.9.7 Placeholder type specifiers") is ill-formed[.](#dcl.spec.auto.general-8.sentence-1)

[9](#dcl.spec.auto.general-9)

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

If the [*init-declarator-list*](dcl.decl.general#nt:init-declarator-list "9.3.1 General [dcl.decl.general]") contains more than one[*init-declarator*](dcl.decl.general#nt:init-declarator "9.3.1 General [dcl.decl.general]"), they shall all form declarations of
variables[.](#dcl.spec.auto.general-9.sentence-1)

The type of each declared variable is determined
by [placeholder type deduction](#def:placeholder_type_deduction "9.2.9.7.2 Placeholder type deduction [dcl.type.auto.deduct]"),
and if the type that replaces the placeholder type is not the
same in each deduction, the program is ill-formed[.](#dcl.spec.auto.general-9.sentence-2)

[*Example [2](#dcl.spec.auto.general-example-2)*: auto x = 5, *y = &x; // OK, auto is intauto a = 5, b = { 1, 2 }; // error: different types for auto â *end example*]

[10](#dcl.spec.auto.general-10)

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

If a function with a declared return type that contains a placeholder type has
multiple non-discarded return statements, the return type is deduced for each
such return statement[.](#dcl.spec.auto.general-10.sentence-1)

If the type deduced is not the same in each
deduction, the program is ill-formed[.](#dcl.spec.auto.general-10.sentence-2)

[11](#dcl.spec.auto.general-11)

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

If a function with a declared return type that uses a placeholder type has no
non-discarded return statements, the return type is deduced as though from areturn statement with no operand at the closing brace of the function
body[.](#dcl.spec.auto.general-11.sentence-1)

[*Example [3](#dcl.spec.auto.general-example-3)*: auto f() { } // OK, return type is voidauto* g() { } // error: cannot deduce auto* from void() â *end example*]

[12](#dcl.spec.auto.general-12)

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

An exported function
with a declared return type that uses a placeholder type
shall be defined in the translation unit
containing its exported declaration,
outside the [*private-module-fragment*](module.private.frag#nt:private-module-fragment "10.5 Private module fragment [module.private.frag]") (if any)[.](#dcl.spec.auto.general-12.sentence-1)

[*Note [2](#dcl.spec.auto.general-note-2)*:

The deduced return type cannot have
a name with internal linkage ([[basic.link]](basic.link "6.7 Program and linkage"))[.](#dcl.spec.auto.general-12.sentence-2)

â *end note*]

[13](#dcl.spec.auto.general-13)

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

If a variable or function with an undeduced placeholder type is named by an
expression ([[basic.def.odr]](basic.def.odr "6.3 One-definition rule")), the program is ill-formed[.](#dcl.spec.auto.general-13.sentence-1)

Once a
non-discarded return statement has been seen in a function, however, the return type deduced
from that statement can be used in the rest of the function, including in otherreturn statements[.](#dcl.spec.auto.general-13.sentence-2)

[*Example [4](#dcl.spec.auto.general-example-4)*: auto n = n; // error: n's initializer refers to nauto f();void g() { &f; } // error: f's return type is unknownauto sum(int i) {if (i == 1)return i; // sum's return type is intelsereturn sum(i-1)+i; // OK, sum's return type has been deduced} â *end example*]

[14](#dcl.spec.auto.general-14)

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

A result binding never has
an undeduced placeholder type ([[dcl.contract.res]](dcl.contract.res "9.4.2 Referring to the result object"))[.](#dcl.spec.auto.general-14.sentence-1)

[*Example [5](#dcl.spec.auto.general-example-5)*: auto f() post(r : r == 7) // OK{return 7;} â *end example*]

[15](#dcl.spec.auto.general-15)

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

Return type deduction for a templated
function with a placeholder in its
declared type occurs when the definition is instantiated even if the function
body contains a return statement with a non-type-dependent operand[.](#dcl.spec.auto.general-15.sentence-1)

[*Note [3](#dcl.spec.auto.general-note-3)*:

Therefore, any use of a specialization of the function template will
cause an implicit instantiation[.](#dcl.spec.auto.general-15.sentence-2)

Any errors that arise from this instantiation
are not in the immediate context of the function type and can result in the
program being ill-formed ([[temp.deduct]](temp.deduct "13.10.3 Template argument deduction"))[.](#dcl.spec.auto.general-15.sentence-3)

â *end note*]

[*Example [6](#dcl.spec.auto.general-example-6)*: template <class T> auto f(T t) { return t; } // return type deduced at instantiation timetypedef decltype(f(1)) fint_t; // instantiates f<int> to deduce return typetemplate<class T> auto f(T* t) { return *t; }void g() { int (*p)(int*) = &f; } // instantiates both fs to determine return types,// chooses second â *end example*]

[16](#dcl.spec.auto.general-16)

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

If a function or function template F has
a declared return type that uses a placeholder type,
redeclarations or specializations of F shall use that
placeholder type, not a deduced type;
otherwise, they shall not use a placeholder type[.](#dcl.spec.auto.general-16.sentence-1)

[*Example [7](#dcl.spec.auto.general-example-7)*: auto f();auto f() { return 42; } // return type is intauto f(); // OKint f(); // error: auto and int don't matchdecltype(auto) f(); // error: auto and decltype(auto) don't matchtemplate <typename T> auto g(T t) { return t; } // #1template auto g(int); // OK, return type is inttemplate char g(char); // error: no matching templatetemplate<> auto g(double); // OK, forward declaration with unknown return typetemplate <class T> T g(T t) { return t; } // OK, not functionally equivalent to #1template char g(char); // OK, now there is a matching templatetemplate auto g(float); // still matches #1void h() { return g(42); } // error: ambiguoustemplate <typename T> struct A {friend T frf(T);};auto frf(int i) { return i; } // not a friend of A<int>extern int v;auto v = 17; // OK, redeclares vstruct S {static int i;};auto S::i = 23; // OK â *end example*]

[17](#dcl.spec.auto.general-17)

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

A function declared with a return type that uses a placeholder type shall not
be virtual ([[class.virtual]](class.virtual "11.7.3 Virtual functions"))[.](#dcl.spec.auto.general-17.sentence-1)

[18](#dcl.spec.auto.general-18)

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

A function declared with a return type that uses a placeholder type shall not
be a coroutine ([[dcl.fct.def.coroutine]](dcl.fct.def.coroutine "9.6.4 Coroutine definitions"))[.](#dcl.spec.auto.general-18.sentence-1)

[19](#dcl.spec.auto.general-19)

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

An [explicit instantiation declaration](temp.explicit "13.9.3 Explicit instantiation [temp.explicit]") does not cause the
instantiation of an entity declared using a placeholder type, but it also does
not prevent that entity from being instantiated as needed to determine its
type[.](#dcl.spec.auto.general-19.sentence-1)

[*Example [8](#dcl.spec.auto.general-example-8)*: template <typename T> auto f(T t) { return t; }extern template auto f(int); // does not instantiate f<int>int (*p)(int) = f; // instantiates f<int> to determine its return type, but an explicit// instantiation definition is still required somewhere in the program â *end example*]

#### [9.2.9.7.2](#auto.deduct) Placeholder type deduction [[dcl.type.auto.deduct]](dcl.type.auto.deduct)

[1](#auto.deduct-1)

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

[*Placeholder type deduction*](#def:placeholder_type_deduction "9.2.9.7.2 Placeholder type deduction [dcl.type.auto.deduct]") is the process by which
a type containing a placeholder type
is replaced by a deduced type[.](#auto.deduct-1.sentence-1)

[2](#auto.deduct-2)

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

A type T containing a placeholder type,
and a corresponding [*initializer-clause*](dcl.init.general#nt:initializer-clause "9.5.1 General [dcl.init.general]") E,
are determined as follows:

- [(2.1)](#auto.deduct-2.1)

  For a non-discarded return statement that occurs
in a function declared with a return type
that contains a placeholder type,T is the declared return type[.](#auto.deduct-2.1.sentence-1)

  * [(2.1.1)](#auto.deduct-2.1.1)

      If the return statement has no operand,
then E is void()[.](#auto.deduct-2.1.1.sentence-1)

  * [(2.1.2)](#auto.deduct-2.1.2)

      If the operand is a [*braced-init-list*](dcl.init.general#nt:braced-init-list "9.5.1 General [dcl.init.general]") ([[dcl.init.list]](dcl.init.list "9.5.5 List-initialization")),
the program is ill-formed[.](#auto.deduct-2.1.2.sentence-1)

  * [(2.1.3)](#auto.deduct-2.1.3)

      If the operand is an [*expression*](expr.comma#nt:expression "7.6.20 Comma operator [expr.comma]") X that is not an [*assignment-expression*](expr.assign#nt:assignment-expression "7.6.19 Assignment and compound assignment operators [expr.assign]"),E is (X)[.](#auto.deduct-2.1.3.sentence-1)
      [*Note [1](#auto.deduct-note-1)*:
      A comma expression ([[expr.comma]](expr.comma "7.6.20 Comma operator")) is not
an [*assignment-expression*](expr.assign#nt:assignment-expression "7.6.19 Assignment and compound assignment operators [expr.assign]")[.](#auto.deduct-2.1.3.sentence-2)
 â *end note*]

  * [(2.1.4)](#auto.deduct-2.1.4)

      Otherwise, E is the operand of the return statement[.](#auto.deduct-2.1.4.sentence-1)

   If E has type void,T shall be either[*type-constraint*](temp.param#nt:type-constraint "13.2 Template parameters [temp.param]")opt decltype(auto) orcv [*type-constraint*](temp.param#nt:type-constraint "13.2 Template parameters [temp.param]")opt auto[.](#auto.deduct-2.1.sentence-2)

- [(2.2)](#auto.deduct-2.2)

  For a variable declared with a type
that contains a placeholder type,T is the declared type of the variable[.](#auto.deduct-2.2.sentence-1)

  * [(2.2.1)](#auto.deduct-2.2.1)

      If the initializer of the variable is a [*brace-or-equal-initializer*](dcl.init.general#nt:brace-or-equal-initializer "9.5.1 General [dcl.init.general]") of the form = [*initializer-clause*](dcl.init.general#nt:initializer-clause "9.5.1 General [dcl.init.general]"),E is the [*initializer-clause*](dcl.init.general#nt:initializer-clause "9.5.1 General [dcl.init.general]")[.](#auto.deduct-2.2.1.sentence-1)

  * [(2.2.2)](#auto.deduct-2.2.2)

      If the initializer is a [*braced-init-list*](dcl.init.general#nt:braced-init-list "9.5.1 General [dcl.init.general]"),
it shall consist of a single brace-enclosed [*assignment-expression*](expr.assign#nt:assignment-expression "7.6.19 Assignment and compound assignment operators [expr.assign]") and E is the [*assignment-expression*](expr.assign#nt:assignment-expression "7.6.19 Assignment and compound assignment operators [expr.assign]")[.](#auto.deduct-2.2.2.sentence-1)

  * [(2.2.3)](#auto.deduct-2.2.3)

      If the initializer is a parenthesized [*expression-list*](expr.post.general#nt:expression-list "7.6.1.1 General [expr.post.general]"),
the [*expression-list*](expr.post.general#nt:expression-list "7.6.1.1 General [expr.post.general]") shall be
a single [*assignment-expression*](expr.assign#nt:assignment-expression "7.6.19 Assignment and compound assignment operators [expr.assign]") and E is the [*assignment-expression*](expr.assign#nt:assignment-expression "7.6.19 Assignment and compound assignment operators [expr.assign]")[.](#auto.deduct-2.2.3.sentence-1)

- [(2.3)](#auto.deduct-2.3)

  For an explicit type conversion ([[expr.type.conv]](expr.type.conv "7.6.1.4 Explicit type conversion (functional notation)")),T is the specified type, which shall be auto[.](#auto.deduct-2.3.sentence-1)

  * [(2.3.1)](#auto.deduct-2.3.1)

      If the initializer is a [*braced-init-list*](dcl.init.general#nt:braced-init-list "9.5.1 General [dcl.init.general]"),
it shall consist of a single brace-enclosed [*assignment-expression*](expr.assign#nt:assignment-expression "7.6.19 Assignment and compound assignment operators [expr.assign]") and E is the [*assignment-expression*](expr.assign#nt:assignment-expression "7.6.19 Assignment and compound assignment operators [expr.assign]")[.](#auto.deduct-2.3.1.sentence-1)

  * [(2.3.2)](#auto.deduct-2.3.2)

      If the initializer is a parenthesized [*expression-list*](expr.post.general#nt:expression-list "7.6.1.1 General [expr.post.general]"),
the [*expression-list*](expr.post.general#nt:expression-list "7.6.1.1 General [expr.post.general]") shall be
a single [*assignment-expression*](expr.assign#nt:assignment-expression "7.6.19 Assignment and compound assignment operators [expr.assign]") and E is the [*assignment-expression*](expr.assign#nt:assignment-expression "7.6.19 Assignment and compound assignment operators [expr.assign]")[.](#auto.deduct-2.3.2.sentence-1)

- [(2.4)](#auto.deduct-2.4)

  For a constant template parameter declared with a type
that contains a placeholder type,T is the declared type of the constant template parameter
and E is the corresponding template argument[.](#auto.deduct-2.4.sentence-1)

T shall not be an array type[.](#auto.deduct-2.sentence-2)

[3](#auto.deduct-3)

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

If the [*placeholder-type-specifier*](#nt:placeholder-type-specifier "9.2.9.7.1 General [dcl.spec.auto.general]") is of the form[*type-constraint*](temp.param#nt:type-constraint "13.2 Template parameters [temp.param]")opt auto,
the deduced typeTâ² replacing T is determined using the rules for template argument deduction[.](#auto.deduct-3.sentence-1)

If the initialization is copy-list-initialization,
a declaration of std​::​initializer_list shall precede ([[basic.lookup.general]](basic.lookup.general "6.5.1 General"))
the [*placeholder-type-specifier*](#nt:placeholder-type-specifier "9.2.9.7.1 General [dcl.spec.auto.general]")[.](#auto.deduct-3.sentence-2)

Obtain P fromT by replacing the occurrence of[*type-constraint*](temp.param#nt:type-constraint "13.2 Template parameters [temp.param]")opt auto either with
a new invented type template parameter U or,
if the initialization is copy-list-initialization, withstd​::​initializer_list<U>[.](#auto.deduct-3.sentence-3)

Deduce a value for U using the rules
of [template argument deduction from a function call](temp.deduct.call "13.10.3.2 Deducing template arguments from a function call [temp.deduct.call]"),
where P is a
function template parameter type and
the corresponding argument is E[.](#auto.deduct-3.sentence-4)

If the deduction fails, the declaration is ill-formed[.](#auto.deduct-3.sentence-5)

Otherwise, Tâ² is obtained by
substituting the deduced U into P[.](#auto.deduct-3.sentence-6)

[*Example [1](#auto.deduct-example-1)*: auto x1 = { 1, 2 }; // decltype(x1) is std​::​initializer_list<int>auto x2 = { 1, 2.0 }; // error: cannot deduce element typeauto x3{ 1, 2 }; // error: not a single elementauto x4 = { 3 }; // decltype(x4) is std​::​initializer_list<int>auto x5{ 3 }; // decltype(x5) is int â *end example*]

[*Example [2](#auto.deduct-example-2)*: const auto &i = expr;

The type of i is the deduced type of the parameter u in
the call f(expr) of the following invented function template:template <class U> void f(const U& u);

â *end example*]

[4](#auto.deduct-4)

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

If the [*placeholder-type-specifier*](#nt:placeholder-type-specifier "9.2.9.7.1 General [dcl.spec.auto.general]") is of the form[*type-constraint*](temp.param#nt:type-constraint "13.2 Template parameters [temp.param]")opt decltype(auto),T shall be the
placeholder alone[.](#auto.deduct-4.sentence-1)

The type deduced for T is
determined as described in [[dcl.type.decltype]](#decltype "9.2.9.6 Decltype specifiers"), as thoughE had
been the operand of the decltype[.](#auto.deduct-4.sentence-2)

[*Example [3](#auto.deduct-example-3)*: int i;int&& f();auto x2a(i); // decltype(x2a) is intdecltype(auto) x2d(i); // decltype(x2d) is intauto x3a = i; // decltype(x3a) is intdecltype(auto) x3d = i; // decltype(x3d) is intauto x4a = (i); // decltype(x4a) is intdecltype(auto) x4d = (i); // decltype(x4d) is int&auto x5a = f(); // decltype(x5a) is intdecltype(auto) x5d = f(); // decltype(x5d) is int&&auto x6a = { 1, 2 }; // decltype(x6a) is std​::​initializer_list<int>decltype(auto) x6d = { 1, 2 }; // error: { 1, 2 } is not an expressionauto *x7a = &i; // decltype(x7a) is int*decltype(auto)*x7d = &i; // error: declared type is not plain decltype(auto)auto f1(int x) -> decltype((x)) { return (x); } // return type is int&auto f2(int x) -> decltype(auto) { return (x); } // return type is int&& â *end example*]

[5](#auto.deduct-5)

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

For a [*placeholder-type-specifier*](#nt:placeholder-type-specifier "9.2.9.7.1 General [dcl.spec.auto.general]") with a [*type-constraint*](temp.param#nt:type-constraint "13.2 Template parameters [temp.param]"),
the immediately-declared constraint ([[temp.param]](temp.param "13.2 Template parameters"))
of the [*type-constraint*](temp.param#nt:type-constraint "13.2 Template parameters [temp.param]") for the type deduced for the placeholder
shall be satisfied[.](#auto.deduct-5.sentence-1)

#### [9.2.9.8](#class.deduct) Deduced class template specialization types [[dcl.type.class.deduct]](dcl.type.class.deduct)

[1](#class.deduct-1)

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

If a placeholder for a deduced class type
appears as a [*decl-specifier*](dcl.spec.general#nt:decl-specifier "9.2.1 General [dcl.spec.general]") in the [*decl-specifier-seq*](dcl.spec.general#nt:decl-specifier-seq "9.2.1 General [dcl.spec.general]") of an initializing declaration ([[dcl.init]](dcl.init "9.5 Initializers")) of a variable,
the declared type of the variable shall be cv T,
where T is the placeholder[.](#class.deduct-1.sentence-1)

[*Example [1](#class.deduct-example-1)*: template <class ...T> struct A { A(T...) {}};
A x[29]{}; // error: no declarator operators allowedconst A& y{}; // error: no declarator operators allowed â *end example*]

The placeholder is replaced by the return type
of the function selected by overload resolution
for class template deduction ([[over.match.class.deduct]](over.match.class.deduct "12.2.2.9 Class template argument deduction"))[.](#class.deduct-1.sentence-2)

If the [*decl-specifier-seq*](dcl.spec.general#nt:decl-specifier-seq "9.2.1 General [dcl.spec.general]") is followed by an [*init-declarator-list*](dcl.decl.general#nt:init-declarator-list "9.3.1 General [dcl.decl.general]") or [*member-declarator-list*](class.mem.general#nt:member-declarator-list "11.4.1 General [class.mem.general]") containing more than one [*declarator*](dcl.decl.general#nt:declarator "9.3.1 General [dcl.decl.general]"),
the type that replaces the placeholder shall be the same in each deduction[.](#class.deduct-1.sentence-3)

[2](#class.deduct-2)

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

A placeholder for a deduced class type
can also be used
in the [*type-specifier-seq*](#nt:type-specifier-seq "9.2.9.1 General [dcl.type.general]") in the [*new-type-id*](expr.new#nt:new-type-id "7.6.2.8 New [expr.new]") or [*type-id*](dcl.name#nt:type-id "9.3.2 Type names [dcl.name]") of a [*new-expression*](expr.new#nt:new-expression "7.6.2.8 New [expr.new]") ([[expr.new]](expr.new "7.6.2.8 New")),
as the [*simple-type-specifier*](#nt:simple-type-specifier "9.2.9.3 Simple type specifiers [dcl.type.simple]") in an [explicit type conversion (functional notation)](expr.type.conv "7.6.1.4 Explicit type conversion (functional notation) [expr.type.conv]"),
or
as the [*type-specifier*](#nt:type-specifier "9.2.9.1 General [dcl.type.general]") in the [*parameter-declaration*](dcl.fct#nt:parameter-declaration "9.3.4.6 Functions [dcl.fct]") of a [*template-parameter*](temp.param#nt:template-parameter "13.2 Template parameters [temp.param]") ([[temp.param]](temp.param "13.2 Template parameters"))[.](#class.deduct-2.sentence-1)

A placeholder for a deduced class type
shall not appear in any other context[.](#class.deduct-2.sentence-2)

[3](#class.deduct-3)

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

[*Example [2](#class.deduct-example-2)*: template<class T> struct container { container(T t) {}template<class Iter> container(Iter beg, Iter end);};template<class Iter> container(Iter b, Iter e) -> container<typename std::iterator_traits<Iter>::value_type>;
std::vector<double> v = { /* ... */ };

container c(7); // OK, deduces int for Tauto d = container(v.begin(), v.end()); // OK, deduces double for T container e{5, 6}; // error: int is not an iterator â *end example*]

#### [9.2.9.9](#splice) Type splicing [[dcl.type.splice]](dcl.type.splice)

[splice-type-specifier:](#nt:splice-type-specifier "9.2.9.9 Type splicing [dcl.type.splice]")  
typenameopt [*splice-specifier*](basic.splice#nt:splice-specifier "6.6 Splice specifiers [basic.splice]")  
typenameopt [*splice-specialization-specifier*](basic.splice#nt:splice-specialization-specifier "6.6 Splice specifiers [basic.splice]")

[1](#splice-1)

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

A [*splice-specifier*](basic.splice#nt:splice-specifier "6.6 Splice specifiers [basic.splice]") or[*splice-specialization-specifier*](basic.splice#nt:splice-specialization-specifier "6.6 Splice specifiers [basic.splice]") immediately followed by ​::​ is never interpreted as part of a [*splice-type-specifier*](#nt:splice-type-specifier "9.2.9.9 Type splicing [dcl.type.splice]")[.](#splice-1.sentence-1)

A [*splice-specifier*](basic.splice#nt:splice-specifier "6.6 Splice specifiers [basic.splice]") or[*splice-specialization-specifier*](basic.splice#nt:splice-specialization-specifier "6.6 Splice specifiers [basic.splice]") not preceded by typename is only interpreted as a [*splice-type-specifier*](#nt:splice-type-specifier "9.2.9.9 Type splicing [dcl.type.splice]") within a type-only context ([[temp.res.general]](temp.res.general "13.8.1 General"))[.](#splice-1.sentence-2)

[*Example [1](#splice-example-1)*: template<std::meta::info R> void tfn() {typename [:R:]::type m; // OK, typename applies to the qualified name}struct S { using type = int; };void fn() {[:^^S::type:] *var; // error: [:^^S​::​type:] is an expressiontypename [:^^S::type:] *var; // OK, declares variable with type int*}using alias = [:^^S::type:]; // OK, type-only context â *end example*]

[2](#splice-2)

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

For a [*splice-type-specifier*](#nt:splice-type-specifier "9.2.9.9 Type splicing [dcl.type.splice]") of the formtypenameopt [*splice-specifier*](basic.splice#nt:splice-specifier "6.6 Splice specifiers [basic.splice]"),
the [*splice-specifier*](basic.splice#nt:splice-specifier "6.6 Splice specifiers [basic.splice]") shall designate
a type, a class template, or an alias template[.](#splice-2.sentence-1)

The [*splice-type-specifier*](#nt:splice-type-specifier "9.2.9.9 Type splicing [dcl.type.splice]") designates
the same entity as the [*splice-specifier*](basic.splice#nt:splice-specifier "6.6 Splice specifiers [basic.splice]")[.](#splice-2.sentence-2)

[3](#splice-3)

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

For a [*splice-type-specifier*](#nt:splice-type-specifier "9.2.9.9 Type splicing [dcl.type.splice]") of the formtypenameopt [*splice-specialization-specifier*](basic.splice#nt:splice-specialization-specifier "6.6 Splice specifiers [basic.splice]"),
the [*splice-specifier*](basic.splice#nt:splice-specifier "6.6 Splice specifiers [basic.splice]") of
the [*splice-specialization-specifier*](basic.splice#nt:splice-specialization-specifier "6.6 Splice specifiers [basic.splice]") shall designate a template T that is either a class template or an alias template[.](#splice-3.sentence-1)

The [*splice-type-specifier*](#nt:splice-type-specifier "9.2.9.9 Type splicing [dcl.type.splice]") designates
the specialization of T corresponding to
the template argument list of the [*splice-specialization-specifier*](basic.splice#nt:splice-specialization-specifier "6.6 Splice specifiers [basic.splice]")[.](#splice-3.sentence-2)
