[dcl.type.auto.deduct]

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

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

### 9.2.9 Type specifiers [[dcl.type]](dcl.type#auto.deduct)

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

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

[1](#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[.](#1.sentence-1)

[2](#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)](#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[.](#2.1.sentence-1)

  * [(2.1.1)](#2.1.1)

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

  * [(2.1.2)](#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[.](#2.1.2.sentence-1)

  * [(2.1.3)](#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)[.](#2.1.3.sentence-1)
      [*Note [1](#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]")[.](#2.1.3.sentence-2)
 â *end note*]

  * [(2.1.4)](#2.1.4)

      Otherwise, E is the operand of the return statement[.](#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[.](#2.1.sentence-2)

- [(2.2)](#2.2)

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

  * [(2.2.1)](#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]")[.](#2.2.1.sentence-1)

  * [(2.2.2)](#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]")[.](#2.2.2.sentence-1)

  * [(2.2.3)](#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]")[.](#2.2.3.sentence-1)

- [(2.3)](#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[.](#2.3.sentence-1)

  * [(2.3.1)](#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]")[.](#2.3.1.sentence-1)

  * [(2.3.2)](#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]")[.](#2.3.2.sentence-1)

- [(2.4)](#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[.](#2.4.sentence-1)

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

[3](#3)

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

If the [*placeholder-type-specifier*](dcl.spec.auto.general#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[.](#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*](dcl.spec.auto.general#nt:placeholder-type-specifier "9.2.9.7.1 General [dcl.spec.auto.general]")[.](#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>[.](#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[.](#3.sentence-4)

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

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

[*Example [1](#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](#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](#4)

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

If the [*placeholder-type-specifier*](dcl.spec.auto.general#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[.](#4.sentence-1)

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

[*Example [3](#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](#5)

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

For a [*placeholder-type-specifier*](dcl.spec.auto.general#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[.](#5.sentence-1)
