Init
This commit is contained in:
412
cppdraft/dcl/spec/auto.md
Normal file
412
cppdraft/dcl/spec/auto.md
Normal file
@@ -0,0 +1,412 @@
|
||||
[dcl.spec.auto]
|
||||
|
||||
# 9 Declarations [[dcl]](./#dcl)
|
||||
|
||||
## 9.2 Specifiers [[dcl.spec]](dcl.spec#auto)
|
||||
|
||||
### 9.2.9 Type specifiers [[dcl.type]](dcl.type#dcl.spec.auto)
|
||||
|
||||
#### 9.2.9.7 Placeholder type specifiers [dcl.spec.auto]
|
||||
|
||||
#### [9.2.9.7.1](#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](#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[.](#general-1.sentence-1)
|
||||
|
||||
[2](#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)](#general-2.1)
|
||||
|
||||
function declaration ([[dcl.fct]](dcl.fct "9.3.4.6 Functions")),
|
||||
|
||||
- [(2.2)](#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)](#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[.](#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*](dcl.type.general#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[.](#general-2.sentence-2)
|
||||
|
||||
[*Note [1](#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"))[.](#general-2.sentence-3)
|
||||
|
||||
â *end note*]
|
||||
|
||||
[3](#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"))[.](#general-3.sentence-1)
|
||||
|
||||
[4](#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*](dcl.type.general#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"))[.](#general-4.sentence-1)
|
||||
|
||||
[5](#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[.](#general-5.sentence-1)
|
||||
|
||||
This use is allowed
|
||||
in an initializing declaration ([[dcl.init]](dcl.init "9.5 Initializers")) of a variable[.](#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*](dcl.type.general#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]")[.](#general-5.sentence-3)
|
||||
|
||||
[*Example [1](#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*](dcl.type.general#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"))[.](#general-5.sentence-4)
|
||||
|
||||
[6](#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*](dcl.type.general#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"))[.](#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*](dcl.type.general#nt:type-specifier "9.2.9.1 General [dcl.type.general]")*s* in
|
||||
the [*type-specifier-seq*](dcl.type.general#nt:type-specifier-seq "9.2.9.1 General [dcl.type.general]") or
|
||||
as one of the [*type-specifier*](dcl.type.general#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*](dcl.type.general#nt:type-specifier "9.2.9.1 General [dcl.type.general]")[.](#general-6.sentence-2)
|
||||
|
||||
[7](#general-7)
|
||||
|
||||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/declarations.tex#L1920)
|
||||
|
||||
The auto [*type-specifier*](dcl.type.general#nt:type-specifier "9.2.9.1 General [dcl.type.general]") can also be used
|
||||
as the [*simple-type-specifier*](dcl.type.simple#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)"))[.](#general-7.sentence-1)
|
||||
|
||||
[8](#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] is ill-formed[.](#general-8.sentence-1)
|
||||
|
||||
[9](#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[.](#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[.](#general-9.sentence-2)
|
||||
|
||||
[*Example [2](#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](#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[.](#general-10.sentence-1)
|
||||
|
||||
If the type deduced is not the same in each
|
||||
deduction, the program is ill-formed[.](#general-10.sentence-2)
|
||||
|
||||
[11](#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[.](#general-11.sentence-1)
|
||||
|
||||
[*Example [3](#general-example-3)*: auto f() { } // OK, return type is voidauto* g() { } // error: cannot deduce auto* from void() â *end example*]
|
||||
|
||||
[12](#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)[.](#general-12.sentence-1)
|
||||
|
||||
[*Note [2](#general-note-2)*:
|
||||
|
||||
The deduced return type cannot have
|
||||
a name with internal linkage ([[basic.link]](basic.link "6.7 Program and linkage"))[.](#general-12.sentence-2)
|
||||
|
||||
â *end note*]
|
||||
|
||||
[13](#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[.](#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[.](#general-13.sentence-2)
|
||||
|
||||
[*Example [4](#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](#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"))[.](#general-14.sentence-1)
|
||||
|
||||
[*Example [5](#general-example-5)*: auto f() post(r : r == 7) // OK{return 7;} â *end example*]
|
||||
|
||||
[15](#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[.](#general-15.sentence-1)
|
||||
|
||||
[*Note [3](#general-note-3)*:
|
||||
|
||||
Therefore, any use of a specialization of the function template will
|
||||
cause an implicit instantiation[.](#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"))[.](#general-15.sentence-3)
|
||||
|
||||
â *end note*]
|
||||
|
||||
[*Example [6](#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](#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[.](#general-16.sentence-1)
|
||||
|
||||
[*Example [7](#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](#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"))[.](#general-17.sentence-1)
|
||||
|
||||
[18](#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"))[.](#general-18.sentence-1)
|
||||
|
||||
[19](#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[.](#general-19.sentence-1)
|
||||
|
||||
[*Example [8](#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](#dcl.type.auto.deduct) Placeholder type deduction [[dcl.type.auto.deduct]](dcl.type.auto.deduct)
|
||||
|
||||
[1](#dcl.type.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[.](#dcl.type.auto.deduct-1.sentence-1)
|
||||
|
||||
[2](#dcl.type.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)](#dcl.type.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[.](#dcl.type.auto.deduct-2.1.sentence-1)
|
||||
|
||||
* [(2.1.1)](#dcl.type.auto.deduct-2.1.1)
|
||||
|
||||
If the return statement has no operand,
|
||||
then E is void()[.](#dcl.type.auto.deduct-2.1.1.sentence-1)
|
||||
|
||||
* [(2.1.2)](#dcl.type.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[.](#dcl.type.auto.deduct-2.1.2.sentence-1)
|
||||
|
||||
* [(2.1.3)](#dcl.type.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)[.](#dcl.type.auto.deduct-2.1.3.sentence-1)
|
||||
[*Note [1](#dcl.type.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]")[.](#dcl.type.auto.deduct-2.1.3.sentence-2)
|
||||
â *end note*]
|
||||
|
||||
* [(2.1.4)](#dcl.type.auto.deduct-2.1.4)
|
||||
|
||||
Otherwise, E is the operand of the return statement[.](#dcl.type.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[.](#dcl.type.auto.deduct-2.1.sentence-2)
|
||||
|
||||
- [(2.2)](#dcl.type.auto.deduct-2.2)
|
||||
|
||||
For a variable declared with a type
|
||||
that contains a placeholder type,T is the declared type of the variable[.](#dcl.type.auto.deduct-2.2.sentence-1)
|
||||
|
||||
* [(2.2.1)](#dcl.type.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]")[.](#dcl.type.auto.deduct-2.2.1.sentence-1)
|
||||
|
||||
* [(2.2.2)](#dcl.type.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]")[.](#dcl.type.auto.deduct-2.2.2.sentence-1)
|
||||
|
||||
* [(2.2.3)](#dcl.type.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]")[.](#dcl.type.auto.deduct-2.2.3.sentence-1)
|
||||
|
||||
- [(2.3)](#dcl.type.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[.](#dcl.type.auto.deduct-2.3.sentence-1)
|
||||
|
||||
* [(2.3.1)](#dcl.type.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]")[.](#dcl.type.auto.deduct-2.3.1.sentence-1)
|
||||
|
||||
* [(2.3.2)](#dcl.type.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]")[.](#dcl.type.auto.deduct-2.3.2.sentence-1)
|
||||
|
||||
- [(2.4)](#dcl.type.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[.](#dcl.type.auto.deduct-2.4.sentence-1)
|
||||
|
||||
T shall not be an array type[.](#dcl.type.auto.deduct-2.sentence-2)
|
||||
|
||||
[3](#dcl.type.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[.](#dcl.type.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]")[.](#dcl.type.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>[.](#dcl.type.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[.](#dcl.type.auto.deduct-3.sentence-4)
|
||||
|
||||
If the deduction fails, the declaration is ill-formed[.](#dcl.type.auto.deduct-3.sentence-5)
|
||||
|
||||
Otherwise, Tâ² is obtained by
|
||||
substituting the deduced U into P[.](#dcl.type.auto.deduct-3.sentence-6)
|
||||
|
||||
[*Example [1](#dcl.type.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](#dcl.type.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](#dcl.type.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[.](#dcl.type.auto.deduct-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[.](#dcl.type.auto.deduct-4.sentence-2)
|
||||
|
||||
[*Example [3](#dcl.type.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](#dcl.type.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[.](#dcl.type.auto.deduct-5.sentence-1)
|
||||
264
cppdraft/dcl/spec/auto/general.md
Normal file
264
cppdraft/dcl/spec/auto/general.md
Normal file
@@ -0,0 +1,264 @@
|
||||
[dcl.spec.auto.general]
|
||||
|
||||
# 9 Declarations [[dcl]](./#dcl)
|
||||
|
||||
## 9.2 Specifiers [[dcl.spec]](dcl.spec#auto.general)
|
||||
|
||||
### 9.2.9 Type specifiers [[dcl.type]](dcl.type#dcl.spec.auto.general)
|
||||
|
||||
#### 9.2.9.7 Placeholder type specifiers [[dcl.spec.auto]](dcl.spec.auto#general)
|
||||
|
||||
#### 9.2.9.7.1 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](#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[.](#1.sentence-1)
|
||||
|
||||
[2](#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)](#2.1)
|
||||
|
||||
function declaration ([[dcl.fct]](dcl.fct "9.3.4.6 Functions")),
|
||||
|
||||
- [(2.2)](#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)](#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[.](#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*](dcl.type.general#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[.](#2.sentence-2)
|
||||
|
||||
[*Note [1](#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"))[.](#2.sentence-3)
|
||||
|
||||
â *end note*]
|
||||
|
||||
[3](#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"))[.](#3.sentence-1)
|
||||
|
||||
[4](#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*](dcl.type.general#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"))[.](#4.sentence-1)
|
||||
|
||||
[5](#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[.](#5.sentence-1)
|
||||
|
||||
This use is allowed
|
||||
in an initializing declaration ([[dcl.init]](dcl.init "9.5 Initializers")) of a variable[.](#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*](dcl.type.general#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]")[.](#5.sentence-3)
|
||||
|
||||
[*Example [1](#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*](dcl.type.general#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"))[.](#5.sentence-4)
|
||||
|
||||
[6](#6)
|
||||
|
||||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/declarations.tex#L1906)
|
||||
|
||||
A placeholder type can also be used
|
||||
in the [*type-specifier-seq*](dcl.type.general#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"))[.](#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*](dcl.type.general#nt:type-specifier "9.2.9.1 General [dcl.type.general]")*s* in
|
||||
the [*type-specifier-seq*](dcl.type.general#nt:type-specifier-seq "9.2.9.1 General [dcl.type.general]") or
|
||||
as one of the [*type-specifier*](dcl.type.general#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*](dcl.type.general#nt:type-specifier "9.2.9.1 General [dcl.type.general]")[.](#6.sentence-2)
|
||||
|
||||
[7](#7)
|
||||
|
||||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/declarations.tex#L1920)
|
||||
|
||||
The auto [*type-specifier*](dcl.type.general#nt:type-specifier "9.2.9.1 General [dcl.type.general]") can also be used
|
||||
as the [*simple-type-specifier*](dcl.type.simple#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)"))[.](#7.sentence-1)
|
||||
|
||||
[8](#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[.](#8.sentence-1)
|
||||
|
||||
[9](#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[.](#9.sentence-1)
|
||||
|
||||
The type of each declared variable is determined
|
||||
by [placeholder type deduction](dcl.type.auto.deduct#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[.](#9.sentence-2)
|
||||
|
||||
[*Example [2](#example-2)*: auto x = 5, *y = &x; // OK, auto is intauto a = 5, b = { 1, 2 }; // error: different types for auto â *end example*]
|
||||
|
||||
[10](#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[.](#10.sentence-1)
|
||||
|
||||
If the type deduced is not the same in each
|
||||
deduction, the program is ill-formed[.](#10.sentence-2)
|
||||
|
||||
[11](#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[.](#11.sentence-1)
|
||||
|
||||
[*Example [3](#example-3)*: auto f() { } // OK, return type is voidauto* g() { } // error: cannot deduce auto* from void() â *end example*]
|
||||
|
||||
[12](#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)[.](#12.sentence-1)
|
||||
|
||||
[*Note [2](#note-2)*:
|
||||
|
||||
The deduced return type cannot have
|
||||
a name with internal linkage ([[basic.link]](basic.link "6.7 Program and linkage"))[.](#12.sentence-2)
|
||||
|
||||
â *end note*]
|
||||
|
||||
[13](#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[.](#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[.](#13.sentence-2)
|
||||
|
||||
[*Example [4](#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](#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"))[.](#14.sentence-1)
|
||||
|
||||
[*Example [5](#example-5)*: auto f() post(r : r == 7) // OK{return 7;} â *end example*]
|
||||
|
||||
[15](#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[.](#15.sentence-1)
|
||||
|
||||
[*Note [3](#note-3)*:
|
||||
|
||||
Therefore, any use of a specialization of the function template will
|
||||
cause an implicit instantiation[.](#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"))[.](#15.sentence-3)
|
||||
|
||||
â *end note*]
|
||||
|
||||
[*Example [6](#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](#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[.](#16.sentence-1)
|
||||
|
||||
[*Example [7](#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](#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"))[.](#17.sentence-1)
|
||||
|
||||
[18](#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"))[.](#18.sentence-1)
|
||||
|
||||
[19](#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[.](#19.sentence-1)
|
||||
|
||||
[*Example [8](#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*]
|
||||
82
cppdraft/dcl/spec/general.md
Normal file
82
cppdraft/dcl/spec/general.md
Normal file
@@ -0,0 +1,82 @@
|
||||
[dcl.spec.general]
|
||||
|
||||
# 9 Declarations [[dcl]](./#dcl)
|
||||
|
||||
## 9.2 Specifiers [[dcl.spec]](dcl.spec#general)
|
||||
|
||||
### 9.2.1 General [dcl.spec.general]
|
||||
|
||||
[1](#1)
|
||||
|
||||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/declarations.tex#L431)
|
||||
|
||||
The specifiers that can be used in a declaration are
|
||||
|
||||
[decl-specifier:](#nt:decl-specifier "9.2.1 General [dcl.spec.general]")
|
||||
[*storage-class-specifier*](dcl.stc#nt:storage-class-specifier "9.2.2 Storage class specifiers [dcl.stc]")
|
||||
[*defining-type-specifier*](dcl.type.general#nt:defining-type-specifier "9.2.9.1 General [dcl.type.general]")
|
||||
[*function-specifier*](dcl.fct.spec#nt:function-specifier "9.2.3 Function specifiers [dcl.fct.spec]")
|
||||
friend
|
||||
typedef
|
||||
constexpr
|
||||
consteval
|
||||
constinit
|
||||
inline
|
||||
|
||||
[decl-specifier-seq:](#nt:decl-specifier-seq "9.2.1 General [dcl.spec.general]")
|
||||
[*decl-specifier*](#nt:decl-specifier "9.2.1 General [dcl.spec.general]") [*attribute-specifier-seq*](dcl.attr.grammar#nt:attribute-specifier-seq "9.13.1 Attribute syntax and semantics [dcl.attr.grammar]")opt
|
||||
[*decl-specifier*](#nt:decl-specifier "9.2.1 General [dcl.spec.general]") [*decl-specifier-seq*](#nt:decl-specifier-seq "9.2.1 General [dcl.spec.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 [*decl-specifier-seq*](#nt:decl-specifier-seq "9.2.1 General [dcl.spec.general]") appertains to the type determined by the preceding[*decl-specifier*](#nt:decl-specifier "9.2.1 General [dcl.spec.general]")*s* ([[dcl.meaning]](dcl.meaning "9.3.4 Meaning of declarators"))[.](#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[.](#1.sentence-3)
|
||||
|
||||
[2](#2)
|
||||
|
||||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/declarations.tex#L459)
|
||||
|
||||
At most one of each of the [*decl-specifier*](#nt:decl-specifier "9.2.1 General [dcl.spec.general]")*s*friend, typedef, or inline shall appear in a [*decl-specifier-seq*](#nt:decl-specifier-seq "9.2.1 General [dcl.spec.general]")[.](#2.sentence-1)
|
||||
|
||||
At most one of
|
||||
the constexpr, consteval, and constinit keywords
|
||||
shall appear in a [*decl-specifier-seq*](#nt:decl-specifier-seq "9.2.1 General [dcl.spec.general]")[.](#2.sentence-2)
|
||||
|
||||
[3](#3)
|
||||
|
||||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/declarations.tex#L467)
|
||||
|
||||
If a [*type-name*](dcl.type.simple#nt:type-name "9.2.9.3 Simple type specifiers [dcl.type.simple]") is encountered while parsing a [*decl-specifier-seq*](#nt:decl-specifier-seq "9.2.1 General [dcl.spec.general]"),
|
||||
it is interpreted as part of the [*decl-specifier-seq*](#nt:decl-specifier-seq "9.2.1 General [dcl.spec.general]") if and only if there is no
|
||||
previous [*defining-type-specifier*](dcl.type.general#nt:defining-type-specifier "9.2.9.1 General [dcl.type.general]") other than a [*cv-qualifier*](dcl.decl.general#nt:cv-qualifier "9.3.1 General [dcl.decl.general]") in the[*decl-specifier-seq*](#nt:decl-specifier-seq "9.2.1 General [dcl.spec.general]")[.](#3.sentence-1)
|
||||
|
||||
The sequence shall be self-consistent as
|
||||
described below[.](#3.sentence-2)
|
||||
|
||||
[*Example [1](#example-1)*: typedef char* Pc;static Pc; // error: name missing
|
||||
|
||||
Here, the declaration static Pc is ill-formed because no
|
||||
name was specified for the static variable of type Pc[.](#3.sentence-3)
|
||||
|
||||
To get a
|
||||
variable called Pc, a [*type-specifier*](dcl.type.general#nt:type-specifier "9.2.9.1 General [dcl.type.general]") (other thanconst or volatile) has to be present to indicate that
|
||||
the [*typedef-name*](dcl.typedef#nt:typedef-name "9.2.4 The typedef specifier [dcl.typedef]") Pc is the name being (re)declared,
|
||||
rather than being part of the [*decl-specifier*](#nt:decl-specifier "9.2.1 General [dcl.spec.general]") sequence[.](#3.sentence-4)
|
||||
|
||||
For
|
||||
another example,void f(const Pc); // void f(char* const) (not const char*)void g(const int Pc); // void g(const int)
|
||||
|
||||
â *end example*]
|
||||
|
||||
[4](#4)
|
||||
|
||||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/declarations.tex#L493)
|
||||
|
||||
[*Note [1](#note-1)*:
|
||||
|
||||
Since signed, unsigned, long, and short by default imply int, a [*type-name*](dcl.type.simple#nt:type-name "9.2.9.3 Simple type specifiers [dcl.type.simple]") appearing after one
|
||||
of those specifiers is treated as the name being (re)declared[.](#4.sentence-1)
|
||||
|
||||
[*Example [2](#example-2)*: void h(unsigned Pc); // void h(unsigned int)void k(unsigned int Pc); // void k(unsigned int) â *end example*]
|
||||
|
||||
â *end note*]
|
||||
Reference in New Issue
Block a user