1694 lines
84 KiB
Markdown
1694 lines
84 KiB
Markdown
[dcl.init]
|
||
|
||
# 9 Declarations [[dcl]](./#dcl)
|
||
|
||
## 9.5 Initializers [dcl.init]
|
||
|
||
### [9.5.1](#general) General [[dcl.init.general]](dcl.init.general)
|
||
|
||
[1](#general-1)
|
||
|
||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/declarations.tex#L4912)
|
||
|
||
The process of initialization described in [dcl.init] applies to
|
||
all initializations regardless of syntactic context, including the
|
||
initialization of a function parameter ([[expr.call]](expr.call "7.6.1.3 Function call")), the
|
||
initialization of a return value ([[stmt.return]](stmt.return "8.8.4 The return statement")), or when an
|
||
initializer follows a declarator[.](#general-1.sentence-1)
|
||
|
||
[initializer:](#nt:initializer "9.5.1 General [dcl.init.general]")
|
||
[*brace-or-equal-initializer*](#nt:brace-or-equal-initializer "9.5.1 General [dcl.init.general]")
|
||
( [*expression-list*](expr.post.general#nt:expression-list "7.6.1.1 General [expr.post.general]") )
|
||
|
||
[brace-or-equal-initializer:](#nt:brace-or-equal-initializer "9.5.1 General [dcl.init.general]")
|
||
= [*initializer-clause*](#nt:initializer-clause "9.5.1 General [dcl.init.general]")
|
||
[*braced-init-list*](#nt:braced-init-list "9.5.1 General [dcl.init.general]")
|
||
|
||
[initializer-clause:](#nt:initializer-clause "9.5.1 General [dcl.init.general]")
|
||
[*assignment-expression*](expr.assign#nt:assignment-expression "7.6.19 Assignment and compound assignment operators [expr.assign]")
|
||
[*braced-init-list*](#nt:braced-init-list "9.5.1 General [dcl.init.general]")
|
||
|
||
[braced-init-list:](#nt:braced-init-list "9.5.1 General [dcl.init.general]")
|
||
{ [*initializer-list*](#nt:initializer-list "9.5.1 General [dcl.init.general]") ,opt }
|
||
{ [*designated-initializer-list*](#nt:designated-initializer-list "9.5.1 General [dcl.init.general]") ,opt }
|
||
{ }
|
||
|
||
[initializer-list:](#nt:initializer-list "9.5.1 General [dcl.init.general]")
|
||
[*initializer-clause*](#nt:initializer-clause "9.5.1 General [dcl.init.general]") ...opt
|
||
[*initializer-list*](#nt:initializer-list "9.5.1 General [dcl.init.general]") , [*initializer-clause*](#nt:initializer-clause "9.5.1 General [dcl.init.general]") ...opt
|
||
|
||
[designated-initializer-list:](#nt:designated-initializer-list "9.5.1 General [dcl.init.general]")
|
||
[*designated-initializer-clause*](#nt:designated-initializer-clause "9.5.1 General [dcl.init.general]")
|
||
[*designated-initializer-list*](#nt:designated-initializer-list "9.5.1 General [dcl.init.general]") , [*designated-initializer-clause*](#nt:designated-initializer-clause "9.5.1 General [dcl.init.general]")
|
||
|
||
[designated-initializer-clause:](#nt:designated-initializer-clause "9.5.1 General [dcl.init.general]")
|
||
[*designator*](#nt:designator "9.5.1 General [dcl.init.general]") [*brace-or-equal-initializer*](#nt:brace-or-equal-initializer "9.5.1 General [dcl.init.general]")
|
||
|
||
[designator:](#nt:designator "9.5.1 General [dcl.init.general]")
|
||
. [*identifier*](lex.name#nt:identifier "5.11 Identifiers [lex.name]")
|
||
|
||
[expr-or-braced-init-list:](#nt:expr-or-braced-init-list "9.5.1 General [dcl.init.general]")
|
||
[*expression*](expr.comma#nt:expression "7.6.20 Comma operator [expr.comma]")
|
||
[*braced-init-list*](#nt:braced-init-list "9.5.1 General [dcl.init.general]")
|
||
|
||
[*Note [1](#general-note-1)*:
|
||
|
||
The rules in [dcl.init] apply even if the grammar permits only
|
||
the [*brace-or-equal-initializer*](#nt:brace-or-equal-initializer "9.5.1 General [dcl.init.general]") form
|
||
of [*initializer*](#nt:initializer "9.5.1 General [dcl.init.general]") in a given context[.](#general-1.sentence-2)
|
||
|
||
â *end note*]
|
||
|
||
[2](#general-2)
|
||
|
||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/declarations.tex#L4978)
|
||
|
||
Except for objects declared with the constexpr specifier, for which see [[dcl.constexpr]](dcl.constexpr "9.2.6 The constexpr and consteval specifiers"),
|
||
an [*initializer*](#nt:initializer "9.5.1 General [dcl.init.general]") in the definition of a variable can consist of
|
||
arbitrary expressions involving literals and previously declared
|
||
variables and functions,
|
||
regardless of the variable's storage duration[.](#general-2.sentence-1)
|
||
|
||
[*Example [1](#general-example-1)*: int f(int);int a = 2;int b = f(a);int c(b); â *end example*]
|
||
|
||
[3](#general-3)
|
||
|
||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/declarations.tex#L4993)
|
||
|
||
[*Note [2](#general-note-2)*:
|
||
|
||
Default arguments are more restricted; see [[dcl.fct.default]](dcl.fct.default "9.3.4.7 Default arguments")[.](#general-3.sentence-1)
|
||
|
||
â *end note*]
|
||
|
||
[4](#general-4)
|
||
|
||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/declarations.tex#L4998)
|
||
|
||
[*Note [3](#general-note-3)*:
|
||
|
||
The order of initialization of variables with static storage duration is described in [[basic.start]](basic.start "6.10.3 Start and termination") and [[stmt.dcl]](stmt.dcl "8.10 Declaration statement")[.](#general-4.sentence-1)
|
||
|
||
â *end note*]
|
||
|
||
[5](#general-5)
|
||
|
||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/declarations.tex#L5004)
|
||
|
||
A declaration D of a variable with linkage
|
||
shall not have an [*initializer*](#nt:initializer "9.5.1 General [dcl.init.general]") if D inhabits a block scope[.](#general-5.sentence-1)
|
||
|
||
[6](#general-6)
|
||
|
||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/declarations.tex#L5009)
|
||
|
||
To [*zero-initialize*](#def:zero-initialization "9.5.1 General [dcl.init.general]") an object or reference of type T means:
|
||
|
||
- [(6.1)](#general-6.1)
|
||
|
||
if T is std::meta::info,
|
||
the object is initialized to a null reflection value;
|
||
|
||
- [(6.2)](#general-6.2)
|
||
|
||
if T is any other scalar type ([[basic.types.general]](basic.types.general#term.scalar.type "6.9.1 General")),
|
||
the object is initialized to the value
|
||
obtained by converting the integer literal 0 (zero) to T;[78](#footnote-78 "As specified in [conv.ptr], converting an integer literal whose value is 0 to a pointer type results in a null pointer value.")
|
||
|
||
- [(6.3)](#general-6.3)
|
||
|
||
ifT is a (possibly cv-qualified) non-union class type,
|
||
its padding bits ([[basic.types.general]](basic.types.general#term.padding.bits "6.9.1 General")) are initialized to zero bits and
|
||
each non-static data member,
|
||
each non-virtual base class subobject, and,
|
||
if the object is not a base class subobject,
|
||
each virtual base class subobject
|
||
is zero-initialized;
|
||
|
||
- [(6.4)](#general-6.4)
|
||
|
||
ifT is a (possibly cv-qualified) union type,
|
||
its padding bits ([[basic.types.general]](basic.types.general#term.padding.bits "6.9.1 General")) are initialized to zero bits and
|
||
the
|
||
object's first non-static named
|
||
data member
|
||
is zero-initialized;
|
||
|
||
- [(6.5)](#general-6.5)
|
||
|
||
ifT is an array type,
|
||
each element is zero-initialized;
|
||
|
||
- [(6.6)](#general-6.6)
|
||
|
||
ifT is a reference type, no initialization is performed[.](#general-6.sentence-1)
|
||
|
||
[7](#general-7)
|
||
|
||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/declarations.tex#L5062)
|
||
|
||
To[*default-initialize*](#def:default-initialization "9.5.1 General [dcl.init.general]") an object of typeT means:
|
||
|
||
- [(7.1)](#general-7.1)
|
||
|
||
IfT is a (possibly cv-qualified) class type ([[class]](class "11 Classes")),
|
||
constructors are considered[.](#general-7.1.sentence-1)
|
||
The applicable constructors are
|
||
enumerated ([[over.match.ctor]](over.match.ctor "12.2.2.4 Initialization by constructor")), and the best one for the[*initializer*](#nt:initializer "9.5.1 General [dcl.init.general]") () is chosen through
|
||
overload resolution ([[over.match]](over.match "12.2 Overload resolution"))[.](#general-7.1.sentence-2)
|
||
The constructor thus selected
|
||
is called, with an empty argument list, to initialize the object[.](#general-7.1.sentence-3)
|
||
|
||
- [(7.2)](#general-7.2)
|
||
|
||
IfT is an array type,
|
||
the semantic constraints of default-initializing a hypothetical element
|
||
shall be met and
|
||
each element is default-initialized[.](#general-7.2.sentence-1)
|
||
|
||
- [(7.3)](#general-7.3)
|
||
|
||
If T is std::meta::info, the object is zero-initialized[.](#general-7.3.sentence-1)
|
||
|
||
- [(7.4)](#general-7.4)
|
||
|
||
Otherwise,
|
||
no initialization is performed[.](#general-7.4.sentence-1)
|
||
|
||
[8](#general-8)
|
||
|
||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/declarations.tex#L5095)
|
||
|
||
A class type T is [*const-default-constructible*](#def:const-default-constructible "9.5.1 General [dcl.init.general]") if
|
||
default-initialization of T would invoke
|
||
a user-provided constructor of T (not inherited from a base class)
|
||
or if
|
||
|
||
- [(8.1)](#general-8.1)
|
||
|
||
each direct non-variant non-static data member M of T has a default member initializer
|
||
or, if M is of class type X (or array thereof),X is const-default-constructible,
|
||
|
||
- [(8.2)](#general-8.2)
|
||
|
||
if T is a union with at least one non-static data member,
|
||
exactly one variant member has a default member initializer,
|
||
|
||
- [(8.3)](#general-8.3)
|
||
|
||
if T is not a union,
|
||
for each anonymous union member with at least one non-static data member (if any),
|
||
exactly one non-static data member has a default member initializer, and
|
||
|
||
- [(8.4)](#general-8.4)
|
||
|
||
each potentially constructed base class of T is const-default-constructible[.](#general-8.sentence-1)
|
||
|
||
If a program calls for the default-initialization of an object of a
|
||
const-qualified type T,T shall be std::meta::
|
||
info or a const-default-constructible class type,
|
||
or array thereof[.](#general-8.sentence-2)
|
||
|
||
[9](#general-9)
|
||
|
||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/declarations.tex#L5123)
|
||
|
||
To[*value-initialize*](#def:value-initialization "9.5.1 General [dcl.init.general]") an object of typeT means:
|
||
|
||
- [(9.1)](#general-9.1)
|
||
|
||
IfT is a (possibly cv-qualified) class type ([[class]](class "11 Classes")), then
|
||
let C be the constructor selected to
|
||
default-initialize the object, if any[.](#general-9.1.sentence-1)
|
||
If C is not user-provided, the object is first zero-initialized[.](#general-9.1.sentence-2)
|
||
In all cases, the object is then default-initialized[.](#general-9.1.sentence-3)
|
||
|
||
- [(9.2)](#general-9.2)
|
||
|
||
IfT is an array type,
|
||
the semantic constraints of value-initializing a hypothetical element
|
||
shall be met and
|
||
each element is value-initialized[.](#general-9.2.sentence-1)
|
||
|
||
- [(9.3)](#general-9.3)
|
||
|
||
Otherwise, the object is zero-initialized[.](#general-9.3.sentence-1)
|
||
|
||
[10](#general-10)
|
||
|
||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/declarations.tex#L5152)
|
||
|
||
A program that calls for default-initialization
|
||
or value-initialization
|
||
of an entity
|
||
of reference type is ill-formed[.](#general-10.sentence-1)
|
||
|
||
[11](#general-11)
|
||
|
||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/declarations.tex#L5158)
|
||
|
||
[*Note [4](#general-note-4)*:
|
||
|
||
For every object with static storage duration,
|
||
static initialization ([[basic.start.static]](basic.start.static "6.10.3.2 Static initialization")) is performed
|
||
at program startup before any other initialization takes place[.](#general-11.sentence-1)
|
||
|
||
In some cases, additional initialization is done later[.](#general-11.sentence-2)
|
||
|
||
â *end note*]
|
||
|
||
[12](#general-12)
|
||
|
||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/declarations.tex#L5166)
|
||
|
||
If no initializer is specified for an object, the object is default-initialized[.](#general-12.sentence-1)
|
||
|
||
[13](#general-13)
|
||
|
||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/declarations.tex#L5169)
|
||
|
||
If the entity being initialized does not have class or array type, the[*expression-list*](expr.post.general#nt:expression-list "7.6.1.1 General [expr.post.general]") in a
|
||
parenthesized initializer shall be a single expression[.](#general-13.sentence-1)
|
||
|
||
[14](#general-14)
|
||
|
||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/declarations.tex#L5174)
|
||
|
||
The initialization that occurs in the = form of a[*brace-or-equal-initializer*](#nt:brace-or-equal-initializer "9.5.1 General [dcl.init.general]") or[*condition*](stmt.pre#nt:condition "8.1 Preamble [stmt.pre]") ([[stmt.select]](stmt.select "8.5 Selection statements")),
|
||
as well as in argument passing, function return,
|
||
throwing an exception ([[except.throw]](except.throw "14.2 Throwing an exception")),
|
||
handling an exception ([[except.handle]](except.handle "14.4 Handling an exception")),
|
||
and aggregate member initialization other than by a[*designated-initializer-clause*](#nt:designated-initializer-clause "9.5.1 General [dcl.init.general]") ([[dcl.init.aggr]](#aggr "9.5.2 Aggregates")),
|
||
is called[*copy-initialization*](#def:copy-initialization "9.5.1 General [dcl.init.general]")[.](#general-14.sentence-1)
|
||
|
||
[*Note [5](#general-note-5)*:
|
||
|
||
Copy-initialization can invoke a move ([[class.copy.ctor]](class.copy.ctor "11.4.5.3 Copy/move constructors"))[.](#general-14.sentence-2)
|
||
|
||
â *end note*]
|
||
|
||
[15](#general-15)
|
||
|
||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/declarations.tex#L5191)
|
||
|
||
The initialization that occurs
|
||
|
||
- [(15.1)](#general-15.1)
|
||
|
||
for an [*initializer*](#nt:initializer "9.5.1 General [dcl.init.general]") that is a
|
||
parenthesized [*expression-list*](expr.post.general#nt:expression-list "7.6.1.1 General [expr.post.general]") or a [*braced-init-list*](#nt:braced-init-list "9.5.1 General [dcl.init.general]"),
|
||
|
||
- [(15.2)](#general-15.2)
|
||
|
||
for a [*new-initializer*](expr.new#nt:new-initializer "7.6.2.8 New [expr.new]") ([[expr.new]](expr.new "7.6.2.8 New")),
|
||
|
||
- [(15.3)](#general-15.3)
|
||
|
||
in a static_cast expression ([[expr.static.cast]](expr.static.cast "7.6.1.9 Static cast")),
|
||
|
||
- [(15.4)](#general-15.4)
|
||
|
||
in a functional notation type conversion ([[expr.type.conv]](expr.type.conv "7.6.1.4 Explicit type conversion (functional notation)")), and
|
||
|
||
- [(15.5)](#general-15.5)
|
||
|
||
in the [*braced-init-list*](#nt:braced-init-list "9.5.1 General [dcl.init.general]") form of a [*condition*](stmt.pre#nt:condition "8.1 Preamble [stmt.pre]")
|
||
|
||
is called[*direct-initialization*](#def:direct-initialization "9.5.1 General [dcl.init.general]")[.](#general-15.sentence-1)
|
||
|
||
[16](#general-16)
|
||
|
||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/declarations.tex#L5204)
|
||
|
||
The semantics of initializers are as follows[.](#general-16.sentence-1)
|
||
|
||
The[*destination type*](#def:destination_type) is the cv-unqualified type of the object or reference being initialized and the[*source type*](#def:source_type) is the type of the initializer expression[.](#general-16.sentence-2)
|
||
|
||
If the initializer is not a single (possibly parenthesized) expression, the
|
||
source type is not defined[.](#general-16.sentence-3)
|
||
|
||
- [(16.1)](#general-16.1)
|
||
|
||
If the initializer is a (non-parenthesized) [*braced-init-list*](#nt:braced-init-list "9.5.1 General [dcl.init.general]") or is = [*braced-init-list*](#nt:braced-init-list "9.5.1 General [dcl.init.general]"), the object or reference
|
||
is list-initialized ([[dcl.init.list]](#list "9.5.5 List-initialization"))[.](#general-16.1.sentence-1)
|
||
|
||
- [(16.2)](#general-16.2)
|
||
|
||
If the destination type is a reference type, see [[dcl.init.ref]](#ref "9.5.4 References")[.](#general-16.2.sentence-1)
|
||
|
||
- [(16.3)](#general-16.3)
|
||
|
||
If the destination type is an array of characters,
|
||
an array of char8_t,
|
||
an array of char16_t,
|
||
an array of char32_t,
|
||
or an array ofwchar_t,
|
||
and the initializer is a [*string-literal*](lex.string#nt:string-literal "5.13.5 String literals [lex.string]"), see [[dcl.init.string]](#string "9.5.3 Character arrays")[.](#general-16.3.sentence-1)
|
||
|
||
- [(16.4)](#general-16.4)
|
||
|
||
If the initializer is (), the object is value-initialized[.](#general-16.4.sentence-1)
|
||
[*Note [6](#general-note-6)*:
|
||
Since() is not permitted by the syntax for[*initializer*](#nt:initializer "9.5.1 General [dcl.init.general]"),X a(); is not the declaration of an object of classX,
|
||
but the declaration of a function taking no arguments and returning anX[.](#general-16.4.sentence-2)
|
||
The form() can appear in certain other initialization contexts ([[expr.new]](expr.new "7.6.2.8 New"), [[expr.type.conv]](expr.type.conv "7.6.1.4 Explicit type conversion (functional notation)"), [[class.base.init]](class.base.init "11.9.3 Initializing bases and members"))[.](#general-16.4.sentence-3)
|
||
â *end note*]
|
||
|
||
- [(16.5)](#general-16.5)
|
||
|
||
Otherwise, if the destination type is an array,
|
||
the object is initialized as follows[.](#general-16.5.sentence-1)
|
||
The [*initializer*](#nt:initializer "9.5.1 General [dcl.init.general]") shall be of the form( [*expression-list*](expr.post.general#nt:expression-list "7.6.1.1 General [expr.post.general]") )[.](#general-16.5.sentence-2)
|
||
Let x1, …, xk be
|
||
the elements of the [*expression-list*](expr.post.general#nt:expression-list "7.6.1.1 General [expr.post.general]")[.](#general-16.5.sentence-3)
|
||
If the destination type is an array of unknown bound,
|
||
it is defined as having k elements[.](#general-16.5.sentence-4)
|
||
Let n denote the array size after this potential adjustment[.](#general-16.5.sentence-5)
|
||
If k is greater than n,
|
||
the program is ill-formed[.](#general-16.5.sentence-6)
|
||
Otherwise, the ith array element is copy-initialized withxi for each 1 ⤠i ⤠k, and
|
||
value-initialized for each k<iâ¤n[.](#general-16.5.sentence-7)
|
||
For each 1â¤i<jâ¤n,
|
||
every value computation and side effect associated with
|
||
the initialization of the ith element of the array
|
||
is sequenced before those associated with
|
||
the initialization of the jth element[.](#general-16.5.sentence-8)
|
||
|
||
- [(16.6)](#general-16.6)
|
||
|
||
Otherwise, if the destination type is a class type:
|
||
* [(16.6.1)](#general-16.6.1)
|
||
|
||
If the initializer expression is a prvalue
|
||
and the cv-unqualified version of the source type
|
||
is the same as the destination type,
|
||
the initializer expression is used to initialize the destination object[.](#general-16.6.1.sentence-1)
|
||
[*Example [2](#general-example-2)*:
|
||
T x = T(T(T())); value-initializes x[.](#general-16.6.1.sentence-2)
|
||
â *end example*]
|
||
|
||
* [(16.6.2)](#general-16.6.2)
|
||
|
||
Otherwise, if the initialization is direct-initialization,
|
||
or if it is copy-initialization where the cv-unqualified version of the source
|
||
type is the same as or is derived from the class of the destination type,
|
||
constructors are considered[.](#general-16.6.2.sentence-1)
|
||
The applicable constructors
|
||
are enumerated ([[over.match.ctor]](over.match.ctor "12.2.2.4 Initialization by constructor")), and the best one is chosen
|
||
through overload resolution ([[over.match]](over.match "12.2 Overload resolution"))[.](#general-16.6.2.sentence-2)
|
||
Then:
|
||
+
|
||
[(16.6.2.1)](#general-16.6.2.1)
|
||
If overload resolution is successful,
|
||
the selected constructor
|
||
is called to initialize the object, with the initializer
|
||
expression or [*expression-list*](expr.post.general#nt:expression-list "7.6.1.1 General [expr.post.general]") as its argument(s)[.](#general-16.6.2.1.sentence-1)
|
||
|
||
+
|
||
[(16.6.2.2)](#general-16.6.2.2)
|
||
Otherwise, if no constructor is viable,
|
||
the destination type is
|
||
an aggregate class, and
|
||
the initializer is a parenthesized [*expression-list*](expr.post.general#nt:expression-list "7.6.1.1 General [expr.post.general]"),
|
||
the object is initialized as follows[.](#general-16.6.2.2.sentence-1)
|
||
Let e1, …, en be the elements of the aggregate ([[dcl.init.aggr]](#aggr "9.5.2 Aggregates"))[.](#general-16.6.2.2.sentence-2)
|
||
Let x1, …, xk be the elements of the [*expression-list*](expr.post.general#nt:expression-list "7.6.1.1 General [expr.post.general]")[.](#general-16.6.2.2.sentence-3)
|
||
If k is greater than n, the program is ill-formed[.](#general-16.6.2.2.sentence-4)
|
||
The element ei is copy-initialized withxi for 1 ⤠i ⤠k[.](#general-16.6.2.2.sentence-5)
|
||
The remaining elements are initialized with
|
||
their default member initializers, if any, and
|
||
otherwise are value-initialized[.](#general-16.6.2.2.sentence-6)
|
||
For each 1â¤i<jâ¤n,
|
||
every value computation and side effect
|
||
associated with the initialization of ei is sequenced before those associated with the initialization of ej[.](#general-16.6.2.2.sentence-7)
|
||
[*Note [7](#general-note-7)*:
|
||
By contrast with direct-list-initialization,
|
||
narrowing conversions ([[dcl.init.list]](#list "9.5.5 List-initialization")) can appear,
|
||
designators are not permitted,
|
||
a temporary object bound to a reference
|
||
does not have its lifetime extended ([[class.temporary]](class.temporary "6.8.7 Temporary objects")), and
|
||
there is no brace elision[.](#general-16.6.2.2.sentence-8)
|
||
[*Example [3](#general-example-3)*: struct A {int a; int&& r;};
|
||
|
||
int f();int n = 10;
|
||
|
||
A a1{1, f()}; // OK, lifetime is extended A a2(1, f()); // well-formed, but dangling reference A a3{1.0, 1}; // error: narrowing conversion A a4(1.0, 1); // well-formed, but dangling reference A a5(1.0, std::move(n)); // OK â *end example*]
|
||
â *end note*]
|
||
|
||
+
|
||
[(16.6.2.3)](#general-16.6.2.3)
|
||
Otherwise, the initialization is ill-formed[.](#general-16.6.2.3.sentence-1)
|
||
|
||
* [(16.6.3)](#general-16.6.3)
|
||
|
||
Otherwise (i.e., for the remaining copy-initialization cases),
|
||
user-defined conversions that can convert from the
|
||
source type to the destination type or (when a conversion function
|
||
is used) to a derived class thereof are enumerated as described in [[over.match.copy]](over.match.copy "12.2.2.5 Copy-initialization of class by user-defined conversion"),
|
||
and the best one is chosen through overload resolution ([[over.match]](over.match "12.2 Overload resolution"))[.](#general-16.6.3.sentence-1)
|
||
If the conversion cannot be done or
|
||
is ambiguous, the initialization is ill-formed[.](#general-16.6.3.sentence-2)
|
||
The function
|
||
selected is called with the initializer expression as its
|
||
argument; if the function is a constructor, the call is a prvalue
|
||
of the cv-unqualified version of the
|
||
destination type whose result object is initialized by the constructor[.](#general-16.6.3.sentence-3)
|
||
The call is used
|
||
to direct-initialize, according to the rules above, the object
|
||
that is the destination of the copy-initialization[.](#general-16.6.3.sentence-4)
|
||
|
||
- [(16.7)](#general-16.7)
|
||
|
||
Otherwise, if the source type
|
||
is a (possibly cv-qualified) class type, conversion functions are
|
||
considered[.](#general-16.7.sentence-1)
|
||
The applicable conversion functions are enumerated ([[over.match.conv]](over.match.conv "12.2.2.6 Initialization by conversion function")),
|
||
and the best one is chosen through overload
|
||
resolution ([[over.match]](over.match "12.2 Overload resolution"))[.](#general-16.7.sentence-2)
|
||
The user-defined conversion so selected
|
||
is called to convert the initializer expression into the
|
||
object being initialized[.](#general-16.7.sentence-3)
|
||
If the conversion cannot be done or is
|
||
ambiguous, the initialization is ill-formed[.](#general-16.7.sentence-4)
|
||
|
||
- [(16.8)](#general-16.8)
|
||
|
||
Otherwise, if the initialization is direct-initialization,
|
||
the source type is std::nullptr_t, and
|
||
the destination type is bool,
|
||
the initial value of the object being initialized is false[.](#general-16.8.sentence-1)
|
||
|
||
- [(16.9)](#general-16.9)
|
||
|
||
Otherwise, the initial value of the object being initialized is
|
||
the (possibly converted) value of the initializer expression[.](#general-16.9.sentence-1)
|
||
A standard conversion sequence ([[conv]](conv "7.3 Standard conversions")) is used
|
||
to convert the initializer expression to
|
||
a prvalue of
|
||
the destination type;
|
||
no user-defined conversions are considered[.](#general-16.9.sentence-2)
|
||
If the conversion cannot
|
||
be done, the initialization is ill-formed[.](#general-16.9.sentence-3)
|
||
When initializing a bit-field with a value that it cannot represent, the
|
||
resulting value of the bit-field isimplementation-defined[.](#general-16.9.sentence-4)
|
||
[*Note [8](#general-note-8)*:
|
||
An expression of type
|
||
â*cv1* Tâ
|
||
can initialize an object of type
|
||
â*cv2* Tâ
|
||
independently of
|
||
the cv-qualifiers*cv1* and *cv2*[.](#general-16.9.sentence-5)
|
||
int a;const int b = a;int c = b; â *end note*]
|
||
|
||
[17](#general-17)
|
||
|
||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/declarations.tex#L5407)
|
||
|
||
An immediate invocation ([[expr.const]](expr.const "7.7 Constant expressions")) that is not evaluated where
|
||
it appears ([[dcl.fct.default]](dcl.fct.default "9.3.4.7 Default arguments"), [[class.mem.general]](class.mem.general "11.4.1 General"))
|
||
is evaluated and checked for whether it is
|
||
a constant expression at the point where
|
||
the enclosing [*initializer*](#nt:initializer "9.5.1 General [dcl.init.general]") is used in
|
||
a function call, a constructor definition, or an aggregate initialization[.](#general-17.sentence-1)
|
||
|
||
[18](#general-18)
|
||
|
||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/declarations.tex#L5415)
|
||
|
||
An [*initializer-clause*](#nt:initializer-clause "9.5.1 General [dcl.init.general]") followed by an ellipsis is a
|
||
pack expansion ([[temp.variadic]](temp.variadic "13.7.4 Variadic templates"))[.](#general-18.sentence-1)
|
||
|
||
[19](#general-19)
|
||
|
||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/declarations.tex#L5419)
|
||
|
||
Initialization includes
|
||
the evaluation of all subexpressions of
|
||
each [*initializer-clause*](#nt:initializer-clause "9.5.1 General [dcl.init.general]") of
|
||
the initializer (possibly nested within [*braced-init-list*](#nt:braced-init-list "9.5.1 General [dcl.init.general]")*s*) and
|
||
the creation of any temporary objects for
|
||
function arguments or return values ([[class.temporary]](class.temporary "6.8.7 Temporary objects"))[.](#general-19.sentence-1)
|
||
|
||
[20](#general-20)
|
||
|
||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/declarations.tex#L5427)
|
||
|
||
If the initializer is a parenthesized [*expression-list*](expr.post.general#nt:expression-list "7.6.1.1 General [expr.post.general]"),
|
||
the expressions are evaluated in the order
|
||
specified for function calls ([[expr.call]](expr.call "7.6.1.3 Function call"))[.](#general-20.sentence-1)
|
||
|
||
[21](#general-21)
|
||
|
||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/declarations.tex#L5432)
|
||
|
||
The same [*identifier*](lex.name#nt:identifier "5.11 Identifiers [lex.name]") shall not appear in multiple [*designator*](#nt:designator "9.5.1 General [dcl.init.general]")*s* of a[*designated-initializer-list*](#nt:designated-initializer-list "9.5.1 General [dcl.init.general]")[.](#general-21.sentence-1)
|
||
|
||
[22](#general-22)
|
||
|
||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/declarations.tex#L5437)
|
||
|
||
An object whose initialization has completed
|
||
is deemed to be constructed,
|
||
even if the object is of non-class type or
|
||
no constructor of the object's class
|
||
is invoked for the initialization[.](#general-22.sentence-1)
|
||
|
||
[*Note [9](#general-note-9)*:
|
||
|
||
Such an object might have been value-initialized
|
||
or initialized by aggregate initialization ([[dcl.init.aggr]](#aggr "9.5.2 Aggregates"))
|
||
or by an inherited constructor ([[class.inhctor.init]](class.inhctor.init "11.9.4 Initialization by inherited constructor"))[.](#general-22.sentence-2)
|
||
|
||
â *end note*]
|
||
|
||
Destroying an object of class type invokes the destructor of the class[.](#general-22.sentence-3)
|
||
|
||
Destroying a scalar type has no effect other than
|
||
ending the lifetime of the object ([[basic.life]](basic.life "6.8.4 Lifetime"))[.](#general-22.sentence-4)
|
||
|
||
Destroying an array destroys each element in reverse subscript order[.](#general-22.sentence-5)
|
||
|
||
[23](#general-23)
|
||
|
||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/declarations.tex#L5453)
|
||
|
||
A declaration that specifies the initialization of a variable,
|
||
whether from an explicit initializer or by default-initialization,
|
||
is called the [*initializing declaration*](#def:initializing_declaration "9.5.1 General [dcl.init.general]") of that variable[.](#general-23.sentence-1)
|
||
|
||
[*Note [10](#general-note-10)*:
|
||
|
||
In most cases
|
||
this is the defining declaration ([[basic.def]](basic.def "6.2 Declarations and definitions")) of the variable,
|
||
but the initializing declaration
|
||
of a non-inline static data member ([[class.static.data]](class.static.data "11.4.9.3 Static data members"))
|
||
can be the declaration within the class definition
|
||
and not the definition (if any) outside it[.](#general-23.sentence-2)
|
||
|
||
â *end note*]
|
||
|
||
[78)](#footnote-78)[78)](#footnoteref-78)
|
||
|
||
As specified in [[conv.ptr]](conv.ptr "7.3.12 Pointer conversions"), converting an integer
|
||
literal whose value is0 to a pointer type results in a null pointer value[.](#footnote-78.sentence-1)
|
||
|
||
### [9.5.2](#aggr) Aggregates [[dcl.init.aggr]](dcl.init.aggr)
|
||
|
||
[1](#aggr-1)
|
||
|
||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/declarations.tex#L5475)
|
||
|
||
An [*aggregate*](#def:aggregate "9.5.2 Aggregates [dcl.init.aggr]") is an array or a class ([[class]](class "11 Classes")) with
|
||
|
||
- [(1.1)](#aggr-1.1)
|
||
|
||
no user-declared or inherited constructors ([[class.ctor]](class.ctor "11.4.5 Constructors")),
|
||
|
||
- [(1.2)](#aggr-1.2)
|
||
|
||
no private or protected direct non-static data members ([[class.access]](class.access "11.8 Member access control")),
|
||
|
||
- [(1.3)](#aggr-1.3)
|
||
|
||
no private or protected direct base classes ([[class.access.base]](class.access.base "11.8.3 Accessibility of base classes and base class members")), and
|
||
|
||
- [(1.4)](#aggr-1.4)
|
||
|
||
no virtual functions ([[class.virtual]](class.virtual "11.7.3 Virtual functions")) or virtual base classes ([[class.mi]](class.mi "11.7.2 Multiple base classes"))[.](#aggr-1.sentence-1)
|
||
|
||
[*Note [1](#aggr-note-1)*:
|
||
|
||
Aggregate initialization does not allow accessing
|
||
protected and private base class' members or constructors[.](#aggr-1.sentence-2)
|
||
|
||
â *end note*]
|
||
|
||
[2](#aggr-2)
|
||
|
||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/declarations.tex#L5492)
|
||
|
||
The [*elements*](#def:aggregate,elements "9.5.2 Aggregates [dcl.init.aggr]") of an aggregate are:
|
||
|
||
- [(2.1)](#aggr-2.1)
|
||
|
||
for an array, the array elements in increasing subscript order, or
|
||
|
||
- [(2.2)](#aggr-2.2)
|
||
|
||
for a class, the direct base classes in declaration order,
|
||
followed by the direct non-static data members ([[class.mem]](class.mem "11.4 Class members"))
|
||
that are not members of an anonymous union, in declaration order[.](#aggr-2.sentence-1)
|
||
|
||
[3](#aggr-3)
|
||
|
||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/declarations.tex#L5503)
|
||
|
||
When an aggregate is initialized by an initializer list
|
||
as specified in [[dcl.init.list]](#list "9.5.5 List-initialization"),
|
||
the elements of the initializer list are taken as initializers
|
||
for the elements of the aggregate[.](#aggr-3.sentence-1)
|
||
|
||
The [*explicitly initialized elements*](#def:explicitly_initialized_elements,aggregate "9.5.2 Aggregates [dcl.init.aggr]") of the aggregate are determined as follows:
|
||
|
||
- [(3.1)](#aggr-3.1)
|
||
|
||
If the initializer list is
|
||
a brace-enclosed [*designated-initializer-list*](#nt:designated-initializer-list "9.5.1 General [dcl.init.general]"),
|
||
the aggregate shall be of class type,
|
||
the [*identifier*](lex.name#nt:identifier "5.11 Identifiers [lex.name]") in each [*designator*](#nt:designator "9.5.1 General [dcl.init.general]") shall name a direct non-static data member of the class, and
|
||
the explicitly initialized elements of the aggregate
|
||
are the elements that are, or contain, those members[.](#aggr-3.1.sentence-1)
|
||
|
||
- [(3.2)](#aggr-3.2)
|
||
|
||
If the initializer list is a brace-enclosed [*initializer-list*](#nt:initializer-list "9.5.1 General [dcl.init.general]"),
|
||
the explicitly initialized elements of the aggregate
|
||
are those for which an element of the initializer list
|
||
appertains to the aggregate element or to a subobject thereof (see below)[.](#aggr-3.2.sentence-1)
|
||
|
||
- [(3.3)](#aggr-3.3)
|
||
|
||
Otherwise, the initializer list must be {},
|
||
and there are no explicitly initialized elements[.](#aggr-3.3.sentence-1)
|
||
|
||
[4](#aggr-4)
|
||
|
||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/declarations.tex#L5529)
|
||
|
||
For each explicitly initialized element:
|
||
|
||
- [(4.1)](#aggr-4.1)
|
||
|
||
If the element is an anonymous union member and
|
||
the initializer list is
|
||
a brace-enclosed [*designated-initializer-list*](#nt:designated-initializer-list "9.5.1 General [dcl.init.general]"),
|
||
the element is initialized by the[*braced-init-list*](#nt:braced-init-list "9.5.1 General [dcl.init.general]") { *D* },
|
||
where *D* is the [*designated-initializer-clause*](#nt:designated-initializer-clause "9.5.1 General [dcl.init.general]") naming a member of the anonymous union member[.](#aggr-4.1.sentence-1)
|
||
There shall be only one such [*designated-initializer-clause*](#nt:designated-initializer-clause "9.5.1 General [dcl.init.general]")[.](#aggr-4.1.sentence-2)
|
||
[*Example [1](#aggr-example-1)*:
|
||
struct C {union {int a; const char* p; }; int x;} c = { .a = 1, .x = 3 }; initializes c.a with 1 and c.x with 3[.](#aggr-4.1.sentence-3)
|
||
â *end example*]
|
||
|
||
- [(4.2)](#aggr-4.2)
|
||
|
||
Otherwise, if the initializer list is
|
||
a brace-enclosed [*designated-initializer-list*](#nt:designated-initializer-list "9.5.1 General [dcl.init.general]"),
|
||
the element is initialized with the [*brace-or-equal-initializer*](#nt:brace-or-equal-initializer "9.5.1 General [dcl.init.general]") of the corresponding [*designated-initializer-clause*](#nt:designated-initializer-clause "9.5.1 General [dcl.init.general]")[.](#aggr-4.2.sentence-1)
|
||
If that initializer is of the form= [*assignment-expression*](expr.assign#nt:assignment-expression "7.6.19 Assignment and compound assignment operators [expr.assign]") and
|
||
a narrowing conversion ([[dcl.init.list]](#list "9.5.5 List-initialization")) is required
|
||
to convert the expression, the program is ill-formed[.](#aggr-4.2.sentence-2)
|
||
[*Note [2](#aggr-note-2)*:
|
||
The form of the initializer determines
|
||
whether copy-initialization or direct-initialization is performed[.](#aggr-4.2.sentence-3)
|
||
â *end note*]
|
||
|
||
- [(4.3)](#aggr-4.3)
|
||
|
||
Otherwise,
|
||
the initializer list is a brace-enclosed [*initializer-list*](#nt:initializer-list "9.5.1 General [dcl.init.general]")[.](#aggr-4.3.sentence-1)
|
||
If an [*initializer-clause*](#nt:initializer-clause "9.5.1 General [dcl.init.general]") appertains to the aggregate element,
|
||
then the aggregate element is copy-initialized from the [*initializer-clause*](#nt:initializer-clause "9.5.1 General [dcl.init.general]")[.](#aggr-4.3.sentence-2)
|
||
Otherwise,
|
||
the aggregate element is copy-initialized
|
||
from a brace-enclosed [*initializer-list*](#nt:initializer-list "9.5.1 General [dcl.init.general]") consisting of all of the [*initializer-clause*](#nt:initializer-clause "9.5.1 General [dcl.init.general]")*s* that appertain to subobjects of the aggregate element,
|
||
in the order of appearance[.](#aggr-4.3.sentence-3)
|
||
[*Note [3](#aggr-note-3)*:
|
||
If an initializer is itself an initializer list,
|
||
the element is list-initialized, which will result in a recursive application
|
||
of the rules in this subclause if the element is an aggregate[.](#aggr-4.3.sentence-4)
|
||
â *end note*]
|
||
[*Example [2](#aggr-example-2)*:
|
||
struct A {int x; struct B {int i; int j; } b;} a = { 1, { 2, 3 } }; initializesa.x with 1,a.b.i with 2,a.b.j with 3[.](#aggr-4.3.sentence-5)
|
||
struct base1 { int b1, b2 = 42; };struct base2 { base2() { b3 = 42; }int b3;};struct derived : base1, base2 {int d;};
|
||
|
||
derived d1{{1, 2}, {}, 4};
|
||
derived d2{{}, {}, 4}; initializesd1.b1 with 1,d1.b2 with 2,d1.b3 with 42,d1.d with 4, andd2.b1 with 0,d2.b2 with 42,d2.b3 with 42,d2.d with 4[.](#aggr-4.3.sentence-6)
|
||
â *end example*]
|
||
|
||
[5](#aggr-5)
|
||
|
||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/declarations.tex#L5628)
|
||
|
||
For a non-union aggregate,
|
||
each element that is not an explicitly initialized element
|
||
is initialized as follows:
|
||
|
||
- [(5.1)](#aggr-5.1)
|
||
|
||
If the element has a default member initializer ([[class.mem]](class.mem "11.4 Class members")),
|
||
the element is initialized from that initializer[.](#aggr-5.1.sentence-1)
|
||
|
||
- [(5.2)](#aggr-5.2)
|
||
|
||
Otherwise, if the element is not a reference, the element
|
||
is copy-initialized from an empty initializer list ([[dcl.init.list]](#list "9.5.5 List-initialization"))[.](#aggr-5.2.sentence-1)
|
||
|
||
- [(5.3)](#aggr-5.3)
|
||
|
||
Otherwise, the program is ill-formed[.](#aggr-5.3.sentence-1)
|
||
|
||
If the aggregate is a union and the initializer list is empty, then
|
||
|
||
- [(5.4)](#aggr-5.4)
|
||
|
||
if any variant member has a default member initializer,
|
||
that member is initialized from its default member initializer;
|
||
|
||
- [(5.5)](#aggr-5.5)
|
||
|
||
otherwise, the first member of the union (if any)
|
||
is copy-initialized from an empty initializer list[.](#aggr-5.sentence-2)
|
||
|
||
[6](#aggr-6)
|
||
|
||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/declarations.tex#L5652)
|
||
|
||
[*Example [3](#aggr-example-3)*:
|
||
|
||
struct S { int a; const char* b; int c; int d = b[a]; };
|
||
S ss = { 1, "asdf" }; initializesss.a with 1,ss.b with "asdf",ss.c with the value of an expression of the formint{} (that is, 0), and ss.d with the value of ss.b[ss.a] (that is, 's')[.](#aggr-6.sentence-1)
|
||
|
||
struct A { string a; int b = 42; int c = -1;};
|
||
|
||
A{.c=21} has the following steps:
|
||
|
||
- [(6.1)](#aggr-6.1)
|
||
|
||
Initialize a with {}
|
||
|
||
- [(6.2)](#aggr-6.2)
|
||
|
||
Initialize b with = 42
|
||
|
||
- [(6.3)](#aggr-6.3)
|
||
|
||
Initialize c with = 21
|
||
|
||
â *end example*]
|
||
|
||
[7](#aggr-7)
|
||
|
||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/declarations.tex#L5685)
|
||
|
||
The initializations of the elements of the aggregate
|
||
are evaluated in the element order[.](#aggr-7.sentence-1)
|
||
|
||
That is,
|
||
all value computations and side effects associated with a given element
|
||
are sequenced before
|
||
those of any element that follows it in order[.](#aggr-7.sentence-2)
|
||
|
||
[8](#aggr-8)
|
||
|
||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/declarations.tex#L5693)
|
||
|
||
An aggregate that is a class can also be initialized with a single
|
||
expression not enclosed in braces, as described in [dcl.init][.](#aggr-8.sentence-1)
|
||
|
||
[9](#aggr-9)
|
||
|
||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/declarations.tex#L5697)
|
||
|
||
The destructor for each element of class type
|
||
other than an anonymous union member
|
||
is potentially invoked ([[class.dtor]](class.dtor "11.4.7 Destructors"))
|
||
from the context where the aggregate initialization occurs[.](#aggr-9.sentence-1)
|
||
|
||
[*Note [4](#aggr-note-4)*:
|
||
|
||
This provision ensures that destructors can be called
|
||
for fully-constructed subobjects
|
||
in case an exception is thrown ([[except.ctor]](except.ctor "14.3 Stack unwinding"))[.](#aggr-9.sentence-2)
|
||
|
||
â *end note*]
|
||
|
||
[10](#aggr-10)
|
||
|
||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/declarations.tex#L5708)
|
||
|
||
The number of elements ([[dcl.array]](dcl.array "9.3.4.5 Arrays")) in an array of unknown bound
|
||
initialized with a brace-enclosed [*initializer-list*](#nt:initializer-list "9.5.1 General [dcl.init.general]") is the number of explicitly initialized elements of the array[.](#aggr-10.sentence-1)
|
||
|
||
[*Example [4](#aggr-example-4)*:
|
||
|
||
int x[] = { 1, 3, 5 }; declares and initializesx as a one-dimensional array that has three elements
|
||
since no size was specified and there are three initializers[.](#aggr-10.sentence-2)
|
||
|
||
â *end example*]
|
||
|
||
[*Example [5](#aggr-example-5)*:
|
||
|
||
Instruct X { int i, j, k; };
|
||
X a[] = { 1, 2, 3, 4, 5, 6 };
|
||
X b[2] = { { 1, 2, 3 }, { 4, 5, 6 } };a and b have the same value[.](#aggr-10.sentence-3)
|
||
|
||
â *end example*]
|
||
|
||
An array of unknown bound shall not be initialized with
|
||
an empty [*braced-init-list*](#nt:braced-init-list "9.5.1 General [dcl.init.general]") {}[.](#aggr-10.sentence-4)[79](#footnote-79 "The syntax provides for empty braced-init-lists, but nonetheless C++ does not have zero length arrays.")
|
||
|
||
[*Note [5](#aggr-note-5)*:
|
||
|
||
A default member initializer does not determine the bound for a member
|
||
array of unknown bound[.](#aggr-10.sentence-5)
|
||
|
||
Since the default member initializer is
|
||
ignored if a suitable [*mem-initializer*](class.base.init#nt:mem-initializer "11.9.3 Initializing bases and members [class.base.init]") is present ([[class.base.init]](class.base.init "11.9.3 Initializing bases and members")),
|
||
the default member initializer is not
|
||
considered to initialize the array of unknown bound[.](#aggr-10.sentence-6)
|
||
|
||
[*Example [6](#aggr-example-6)*: struct S {int y[] = { 0 }; // error: non-static data member of incomplete type}; â *end example*]
|
||
|
||
â *end note*]
|
||
|
||
[11](#aggr-11)
|
||
|
||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/declarations.tex#L5751)
|
||
|
||
[*Note [6](#aggr-note-6)*:
|
||
|
||
Static data members,
|
||
non-static data members of anonymous union members,
|
||
and
|
||
unnamed bit-fields
|
||
are not considered elements of the aggregate[.](#aggr-11.sentence-1)
|
||
|
||
[*Example [7](#aggr-example-7)*: struct A {int i; static int s; int j; int :17; int k;} a = { 1, 2, 3 };
|
||
|
||
Here, the second initializer 2 initializesa.j and not the static data memberA::s, and the third initializer 3 initializes a.k and not the unnamed bit-field before it[.](#aggr-11.sentence-2)
|
||
|
||
â *end example*]
|
||
|
||
â *end note*]
|
||
|
||
[12](#aggr-12)
|
||
|
||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/declarations.tex#L5777)
|
||
|
||
If a member has a default member initializer
|
||
and a potentially-evaluated subexpression thereof is an aggregate
|
||
initialization that would use that default member initializer,
|
||
the program is ill-formed[.](#aggr-12.sentence-1)
|
||
|
||
[*Example [8](#aggr-example-8)*: struct A;extern A a;struct A {const A& a1 { A{a,a} }; // OKconst A& a2 { A{} }; // error};
|
||
A a{a,a}; // OKstruct B {int n = B{}.n; // error}; â *end example*]
|
||
|
||
[13](#aggr-13)
|
||
|
||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/declarations.tex#L5798)
|
||
|
||
When initializing a multidimensional array,
|
||
the[*initializer-clause*](#nt:initializer-clause "9.5.1 General [dcl.init.general]")*s* initialize the elements with the last (rightmost) index of the array
|
||
varying the fastest ([[dcl.array]](dcl.array "9.3.4.5 Arrays"))[.](#aggr-13.sentence-1)
|
||
|
||
[*Example [9](#aggr-example-9)*:
|
||
|
||
int x[2][2] = { 3, 1, 4, 2 }; initializesx[0][0] to3,x[0][1] to1,x[1][0] to4,
|
||
andx[1][1] to2[.](#aggr-13.sentence-2)
|
||
|
||
On the other hand,float y[4][3] = {{ 1 }, { 2 }, { 3 }, { 4 }}; initializes the first column ofy (regarded as a two-dimensional array)
|
||
and leaves the rest zero[.](#aggr-13.sentence-3)
|
||
|
||
â *end example*]
|
||
|
||
[14](#aggr-14)
|
||
|
||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/declarations.tex#L5834)
|
||
|
||
Each [*initializer-clause*](#nt:initializer-clause "9.5.1 General [dcl.init.general]") in
|
||
a brace-enclosed [*initializer-list*](#nt:initializer-list "9.5.1 General [dcl.init.general]") is said to [*appertain*](dcl.attr.grammar#def:appertain "9.13.1 Attribute syntax and semantics [dcl.attr.grammar]") to an element of the aggregate being initialized or
|
||
to an element of one of its subaggregates[.](#aggr-14.sentence-1)
|
||
|
||
Considering the sequence of [*initializer-clause*](#nt:initializer-clause "9.5.1 General [dcl.init.general]")*s*,
|
||
and the sequence of aggregate elements
|
||
initially formed as the sequence of elements of the aggregate being initialized
|
||
and potentially modified as described below,
|
||
each [*initializer-clause*](#nt:initializer-clause "9.5.1 General [dcl.init.general]") appertains to
|
||
the corresponding aggregate element if
|
||
|
||
- [(14.1)](#aggr-14.1)
|
||
|
||
the aggregate element is not an aggregate, or
|
||
|
||
- [(14.2)](#aggr-14.2)
|
||
|
||
the [*initializer-clause*](#nt:initializer-clause "9.5.1 General [dcl.init.general]") begins with a left brace, or
|
||
|
||
- [(14.3)](#aggr-14.3)
|
||
|
||
the [*initializer-clause*](#nt:initializer-clause "9.5.1 General [dcl.init.general]") is an expression and
|
||
an implicit conversion sequence can be formed
|
||
that converts the expression to the type of the aggregate element, or
|
||
|
||
- [(14.4)](#aggr-14.4)
|
||
|
||
the aggregate element is an aggregate that itself has no aggregate elements[.](#aggr-14.sentence-2)
|
||
|
||
Otherwise,
|
||
the aggregate element is an aggregate and
|
||
that subaggregate is replaced in the list of aggregate elements by
|
||
the sequence of its own aggregate elements, and
|
||
the appertainment analysis resumes with
|
||
the first such element and the same [*initializer-clause*](#nt:initializer-clause "9.5.1 General [dcl.init.general]")[.](#aggr-14.sentence-3)
|
||
|
||
[*Note [7](#aggr-note-7)*:
|
||
|
||
These rules apply recursively to the aggregate's subaggregates[.](#aggr-14.sentence-4)
|
||
|
||
[*Example [10](#aggr-example-10)*:
|
||
|
||
Instruct S1 { int a, b; };struct S2 { S1 s, t; };
|
||
|
||
S2 x[2] = { 1, 2, 3, 4, 5, 6, 7, 8 };
|
||
S2 y[2] = {{{ 1, 2 }, { 3, 4 }}, {{ 5, 6 }, { 7, 8 }}};x and y have the same value[.](#aggr-14.sentence-5)
|
||
|
||
â *end example*]
|
||
|
||
â *end note*]
|
||
|
||
This process continues
|
||
until all [*initializer-clause*](#nt:initializer-clause "9.5.1 General [dcl.init.general]")*s* have been exhausted[.](#aggr-14.sentence-6)
|
||
|
||
If any [*initializer-clause*](#nt:initializer-clause "9.5.1 General [dcl.init.general]") remains
|
||
that does not appertain to
|
||
an element of the aggregate or one of its subaggregates,
|
||
the program is ill-formed[.](#aggr-14.sentence-7)
|
||
|
||
[*Example [11](#aggr-example-11)*: char cv[4] = { 'a', 's', 'd', 'f', 0 }; // error: too many initializers â *end example*]
|
||
|
||
[15](#aggr-15)
|
||
|
||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/declarations.tex#L5899)
|
||
|
||
[*Example [12](#aggr-example-12)*:
|
||
|
||
float y[4][3] = {{ 1, 3, 5 }, { 2, 4, 6 }, { 3, 5, 7 },}; is a completely-braced initialization:
|
||
1, 3, and 5 initialize the first row of the arrayy[0],
|
||
namelyy[0][0],y[0][1],
|
||
andy[0][2][.](#aggr-15.sentence-1)
|
||
|
||
Likewise the next two lines initializey[1] andy[2][.](#aggr-15.sentence-2)
|
||
|
||
The initializer ends early and thereforey[3]'s
|
||
elements are initialized as if explicitly initialized with an
|
||
expression of the formfloat(),
|
||
that is, are initialized with0.0[.](#aggr-15.sentence-3)
|
||
|
||
In the following example, braces in the[*initializer-list*](#nt:initializer-list "9.5.1 General [dcl.init.general]") are elided;
|
||
however the[*initializer-list*](#nt:initializer-list "9.5.1 General [dcl.init.general]") has the same effect as the completely-braced[*initializer-list*](#nt:initializer-list "9.5.1 General [dcl.init.general]") of the above example,float y[4][3] = {1, 3, 5, 2, 4, 6, 3, 5, 7};
|
||
|
||
The initializer fory begins with a left brace, but the one fory[0] does not,
|
||
therefore three elements from the list are used[.](#aggr-15.sentence-5)
|
||
|
||
Likewise the next three are taken successively fory[1] andy[2][.](#aggr-15.sentence-6)
|
||
|
||
â *end example*]
|
||
|
||
[16](#aggr-16)
|
||
|
||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/declarations.tex#L5953)
|
||
|
||
[*Note [8](#aggr-note-8)*:
|
||
|
||
The initializer for an empty subaggregate is needed
|
||
if any initializers are provided for subsequent elements[.](#aggr-16.sentence-1)
|
||
|
||
[*Example [13](#aggr-example-13)*: struct S { } s;struct A { S s1; int i1;
|
||
S s2; int i2;
|
||
S s3; int i3;} a = {{ }, // Required initialization0,
|
||
s, // Required initialization0}; // Initialization not required for A::s3 because A::i3 is also not initialized â *end example*]
|
||
|
||
â *end note*]
|
||
|
||
[17](#aggr-17)
|
||
|
||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/declarations.tex#L5977)
|
||
|
||
[*Example [14](#aggr-example-14)*: struct A {int i; operator int();};struct B { A a1, a2; int z;};
|
||
A a;
|
||
B b = { 4, a, a };
|
||
|
||
Braces are elided around the[*initializer-clause*](#nt:initializer-clause "9.5.1 General [dcl.init.general]") forb.a1.i[.](#aggr-17.sentence-1)
|
||
|
||
b.a1.i is initialized with 4,b.a2 is initialized witha,b.z is initialized with whatevera.operator int() returns[.](#aggr-17.sentence-2)
|
||
|
||
â *end example*]
|
||
|
||
[18](#aggr-18)
|
||
|
||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/declarations.tex#L6006)
|
||
|
||
[*Note [9](#aggr-note-9)*:
|
||
|
||
An aggregate array or an aggregate class can contain elements of a
|
||
class type with a user-declared constructor ([[class.ctor]](class.ctor "11.4.5 Constructors"))[.](#aggr-18.sentence-1)
|
||
|
||
Initialization of these aggregate objects is described in [[class.expl.init]](class.expl.init "11.9.2 Explicit initialization")[.](#aggr-18.sentence-2)
|
||
|
||
â *end note*]
|
||
|
||
[19](#aggr-19)
|
||
|
||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/declarations.tex#L6014)
|
||
|
||
[*Note [10](#aggr-note-10)*:
|
||
|
||
Whether the initialization of aggregates with static storage duration
|
||
is static or dynamic is specified
|
||
in [[basic.start.static]](basic.start.static "6.10.3.2 Static initialization"), [[basic.start.dynamic]](basic.start.dynamic "6.10.3.3 Dynamic initialization of non-block variables"), and [[stmt.dcl]](stmt.dcl "8.10 Declaration statement")[.](#aggr-19.sentence-1)
|
||
|
||
â *end note*]
|
||
|
||
[20](#aggr-20)
|
||
|
||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/declarations.tex#L6021)
|
||
|
||
When a union is initialized with an initializer list,
|
||
there shall not be more than one
|
||
explicitly initialized element[.](#aggr-20.sentence-1)
|
||
|
||
[*Example [15](#aggr-example-15)*: union u { int a; const char* b; };
|
||
u a = { 1 };
|
||
u b = a;
|
||
u c = 1; // error u d = { 0, "asdf" }; // error u e = { "asdf" }; // error u f = { .b = "asdf" };
|
||
u g = { .a = 1, .b = "asdf" }; // error â *end example*]
|
||
|
||
[21](#aggr-21)
|
||
|
||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/declarations.tex#L6039)
|
||
|
||
[*Note [11](#aggr-note-11)*:
|
||
|
||
As described above,
|
||
the braces around the[*initializer-clause*](#nt:initializer-clause "9.5.1 General [dcl.init.general]") for a union member can be omitted if the
|
||
union is a member of another aggregate[.](#aggr-21.sentence-1)
|
||
|
||
â *end note*]
|
||
|
||
[79)](#footnote-79)[79)](#footnoteref-79)
|
||
|
||
The syntax provides for empty [*braced-init-list*](#nt:braced-init-list "9.5.1 General [dcl.init.general]")*s*,
|
||
but nonetheless C++ does not have zero length arrays[.](#footnote-79.sentence-1)
|
||
|
||
### [9.5.3](#string) Character arrays [[dcl.init.string]](dcl.init.string)
|
||
|
||
[1](#string-1)
|
||
|
||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/declarations.tex#L6051)
|
||
|
||
An array of ordinary character type ([[basic.fundamental]](basic.fundamental "6.9.2 Fundamental types")),char8_t array,char16_t array,char32_t array,
|
||
or wchar_t array
|
||
may be initialized by
|
||
an ordinary string literal,
|
||
UTF-8 string literal,
|
||
UTF-16 string literal,
|
||
UTF-32 string literal, or
|
||
wide string literal,
|
||
respectively, or by an appropriately-typed [*string-literal*](lex.string#nt:string-literal "5.13.5 String literals [lex.string]") enclosed in
|
||
braces ([[lex.string]](lex.string "5.13.5 String literals"))[.](#string-1.sentence-1)
|
||
|
||
Additionally, an array of char orunsigned char may be initialized by
|
||
a UTF-8 string literal, or by
|
||
such a string literal enclosed in braces[.](#string-1.sentence-2)
|
||
|
||
Successive
|
||
characters of the
|
||
value of the [*string-literal*](lex.string#nt:string-literal "5.13.5 String literals [lex.string]") initialize the elements of the array,
|
||
with an integral conversion ([[conv.integral]](conv.integral "7.3.9 Integral conversions"))
|
||
if necessary for the source and destination value[.](#string-1.sentence-3)
|
||
|
||
[*Example [1](#string-example-1)*:
|
||
|
||
char msg[] = "Syntax error on line %s\n"; shows a character array whose members are initialized
|
||
with a[*string-literal*](lex.string#nt:string-literal "5.13.5 String literals [lex.string]")[.](#string-1.sentence-4)
|
||
|
||
Note that because'\n' is a single character and
|
||
because a trailing'\0' is appended,sizeof(msg) is25[.](#string-1.sentence-5)
|
||
|
||
â *end example*]
|
||
|
||
[2](#string-2)
|
||
|
||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/declarations.tex#L6098)
|
||
|
||
There shall not be more initializers than there are array elements[.](#string-2.sentence-1)
|
||
|
||
[*Example [2](#string-example-2)*:
|
||
|
||
char cv[4] = "asdf"; // error is ill-formed since there is no space for the implied trailing'\0'[.](#string-2.sentence-2)
|
||
|
||
â *end example*]
|
||
|
||
[3](#string-3)
|
||
|
||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/declarations.tex#L6108)
|
||
|
||
If there are fewer initializers than there are array elements, each element not
|
||
explicitly initialized shall be zero-initialized ([dcl.init])[.](#string-3.sentence-1)
|
||
|
||
### [9.5.4](#ref) References [[dcl.init.ref]](dcl.init.ref)
|
||
|
||
[1](#ref-1)
|
||
|
||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/declarations.tex#L6115)
|
||
|
||
A variable whose declared type is
|
||
âreference to Tâ ([[dcl.ref]](dcl.ref "9.3.4.3 References"))
|
||
shall be initialized[.](#ref-1.sentence-1)
|
||
|
||
[*Example [1](#ref-example-1)*: int g(int) noexcept;void f() {int i; int& r = i; // r refers to i r = 1; // the value of i becomes 1int* p = &r; // p points to iint& rr = r; // rr refers to what r refers to, that is, to iint (&rg)(int) = g; // rg refers to the function g rg(i); // calls function gint a[3]; int (&ra)[3] = a; // ra refers to the array a ra[1] = i; // modifies a[1]} â *end example*]
|
||
|
||
[2](#ref-2)
|
||
|
||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/declarations.tex#L6137)
|
||
|
||
A reference cannot be changed to refer to another object after initialization[.](#ref-2.sentence-1)
|
||
|
||
[*Note [1](#ref-note-1)*:
|
||
|
||
Assignment to a reference assigns to the object referred to by the reference ([[expr.assign]](expr.assign "7.6.19 Assignment and compound assignment operators"))[.](#ref-2.sentence-2)
|
||
|
||
â *end note*]
|
||
|
||
Argument passing ([[expr.call]](expr.call "7.6.1.3 Function call"))and function value return ([[stmt.return]](stmt.return "8.8.4 The return statement")) are initializations[.](#ref-2.sentence-3)
|
||
|
||
[3](#ref-3)
|
||
|
||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/declarations.tex#L6148)
|
||
|
||
The initializer can be omitted for a reference only in a parameter declaration ([[dcl.fct]](dcl.fct "9.3.4.6 Functions")),
|
||
in the declaration of a function return type, in the declaration of
|
||
a class member within its class definition ([[class.mem]](class.mem "11.4 Class members")), and where theextern specifier is explicitly used[.](#ref-3.sentence-1)
|
||
|
||
[*Example [2](#ref-example-2)*: int& r1; // error: initializer missingextern int& r2; // OK â *end example*]
|
||
|
||
[4](#ref-4)
|
||
|
||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/declarations.tex#L6162)
|
||
|
||
Given types â*cv1* T1â and â*cv2* T2â,
|
||
â*cv1* T1â is [*reference-related*](#def:reference-related "9.5.4 References [dcl.init.ref]") to
|
||
â*cv2* T2â ifT1 is similar ([[conv.qual]](conv.qual "7.3.6 Qualification conversions")) to T2, orT1 is a base class of T2[.](#ref-4.sentence-1)
|
||
|
||
â*cv1* T1â is [*reference-compatible*](#def:reference-compatible "9.5.4 References [dcl.init.ref]") with â*cv2* T2â if
|
||
a prvalue of type âpointer to *cv2* T2â can be converted to
|
||
the type âpointer to *cv1* T1â
|
||
via a standard conversion sequence ([[conv]](conv "7.3 Standard conversions"))[.](#ref-4.sentence-2)
|
||
|
||
In all cases where the reference-compatible relationship
|
||
of two types is used to establish the validity of a reference binding and
|
||
the standard conversion sequence would be ill-formed,
|
||
a program that necessitates such a binding is ill-formed[.](#ref-4.sentence-3)
|
||
|
||
[5](#ref-5)
|
||
|
||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/declarations.tex#L6178)
|
||
|
||
A reference to type â*cv1* T1â is initialized by
|
||
an expression of type â*cv2* T2â as follows:
|
||
|
||
- [(5.1)](#ref-5.1)
|
||
|
||
If the reference is an lvalue reference and the initializer expression
|
||
* [(5.1.1)](#ref-5.1.1)
|
||
|
||
is an lvalue (but is not a
|
||
bit-field), and
|
||
â*cv1* T1â is reference-compatible with
|
||
â*cv2* T2â, or
|
||
|
||
* [(5.1.2)](#ref-5.1.2)
|
||
|
||
has a class type (i.e.,T2 is a class type), where T1 is not reference-related to T2, and can be converted
|
||
to an lvalue of type â*cv3* T3â, where
|
||
â*cv1* T1â is reference-compatible with
|
||
â*cv3* T3â[80](#footnote-80 "This requires a conversion function ([class.conv.fct]) returning a reference type.") (this conversion is selected by enumerating the applicable conversion
|
||
functions ([[over.match.ref]](over.match.ref "12.2.2.7 Initialization by conversion function for direct reference binding")) and choosing the best one through [overload
|
||
resolution](over.match "12.2 Overload resolution [over.match]")),
|
||
|
||
then the reference binds to the initializer expression lvalue in the
|
||
first case and to the lvalue result of the conversion
|
||
in the second case (or, in either case, to the appropriate base class subobject of the object)[.](#ref-5.1.sentence-1)
|
||
[*Note [2](#ref-note-2)*:
|
||
The usual [lvalue-to-rvalue](conv.lval "7.3.2 Lvalue-to-rvalue conversion [conv.lval]"), [array-to-pointer](conv.array "7.3.3 Array-to-pointer conversion [conv.array]"),
|
||
and [function-to-pointer](conv.func "7.3.4 Function-to-pointer conversion [conv.func]") standard
|
||
conversions are not needed, and therefore are suppressed, when such
|
||
direct bindings to lvalues are done[.](#ref-5.1.sentence-2)
|
||
â *end note*]
|
||
[*Example [3](#ref-example-3)*: double d = 2.0;double& rd = d; // rd refers to dconst double& rcd = d; // rcd refers to dstruct A { };struct B : A { operator int&(); } b;
|
||
A& ra = b; // ra refers to A subobject in bconst A& rca = b; // rca refers to A subobject in bint& ir = B(); // ir refers to the result of B::operator int& â *end example*]
|
||
|
||
- [(5.2)](#ref-5.2)
|
||
|
||
Otherwise,
|
||
if the reference is an lvalue reference to a
|
||
type that is not const-qualified or is volatile-qualified,
|
||
the program is ill-formed[.](#ref-5.2.sentence-1)
|
||
[*Example [4](#ref-example-4)*: double& rd2 = 2.0; // error: not an lvalue and reference not constint i = 2;double& rd3 = i; // error: type mismatch and reference not const â *end example*]
|
||
|
||
- [(5.3)](#ref-5.3)
|
||
|
||
Otherwise, if the initializer expression
|
||
* [(5.3.1)](#ref-5.3.1)
|
||
|
||
is an rvalue (but not a bit-field) or an lvalue of function type and
|
||
â*cv1* T1â is
|
||
reference-compatible with â*cv2* T2â, or
|
||
|
||
* [(5.3.2)](#ref-5.3.2)
|
||
|
||
has a class type (i.e., T2 is a class type), where T1 is not reference-related to T2, and can be converted to
|
||
an rvalue of type â*cv3* T3â or
|
||
an lvalue of function type â*cv3* T3â,
|
||
where â*cv1* T1â is
|
||
reference-compatible with â*cv3* T3â (see [[over.match.ref]](over.match.ref "12.2.2.7 Initialization by conversion function for direct reference binding")),
|
||
|
||
then
|
||
the initializer expression in the first case and
|
||
the converted expression in the second case
|
||
is called the converted initializer[.](#ref-5.3.sentence-1)
|
||
If the converted initializer is a prvalue,
|
||
let its type be denoted by T4;
|
||
the temporary materialization conversion ([[conv.rval]](conv.rval "7.3.5 Temporary materialization conversion")) is applied,
|
||
considering the type of the prvalue to be
|
||
â*cv1* T4â ([[conv.qual]](conv.qual "7.3.6 Qualification conversions"))[.](#ref-5.3.sentence-2)
|
||
In any case,
|
||
the reference binds to the resulting glvalue
|
||
(or to an appropriate base class subobject)[.](#ref-5.3.sentence-3)
|
||
[*Example [5](#ref-example-5)*: struct A { };struct B : A { } b;extern B f();const A& rca2 = f(); // binds to the A subobject of the B rvalue. A&& rra = f(); // same as abovestruct X {operator B(); operator int&();} x;const A& r = x; // binds to the A subobject of the result of the conversionint i2 = 42;int&& rri = static_cast<int&&>(i2); // binds directly to i2 B&& rrb = x; // binds directly to the result of operator Bconstexpr int f() {const int &x = 42; const_cast<int &>(x) = 1; // undefined behaviorreturn x;}constexpr int z = f(); // error: not a constant expressiontypedef int *AP[3]; // array of 3 pointer to inttypedef const int *const ACPC[3]; // array of 3 const pointer to const int ACPC &&r = AP{}; // binds directly â *end example*]
|
||
|
||
- [(5.4)](#ref-5.4)
|
||
|
||
Otherwise, T1 shall not be reference-related to T2[.](#ref-5.4.sentence-1)
|
||
|
||
* [(5.4.1)](#ref-5.4.1)
|
||
|
||
If T1 or T2 is a class type,
|
||
user-defined conversions are considered
|
||
using the rules for copy-initialization of an object of type
|
||
â*cv1* T1â by
|
||
user-defined conversion ([dcl.init], [[over.match.copy]](over.match.copy "12.2.2.5 Copy-initialization of class by user-defined conversion"), [[over.match.conv]](over.match.conv "12.2.2.6 Initialization by conversion function"));
|
||
the program is ill-formed if the corresponding non-reference
|
||
copy-initialization would be ill-formed[.](#ref-5.4.1.sentence-1)
|
||
The result E of the call to the
|
||
conversion function, as described for the non-reference
|
||
copy-initialization, is then used to direct-initialize the reference
|
||
using the form (E)[.](#ref-5.4.1.sentence-2)
|
||
For this direct-initialization, user-defined conversions are not considered[.](#ref-5.4.1.sentence-3)
|
||
|
||
* [(5.4.2)](#ref-5.4.2)
|
||
|
||
Otherwise,
|
||
the initializer expression is implicitly converted to a prvalue
|
||
of type âT1â[.](#ref-5.4.2.sentence-1)
|
||
The temporary materialization conversion is applied,
|
||
considering the type of the prvalue to be â*cv1* T1â,
|
||
and the reference is bound to the result[.](#ref-5.4.2.sentence-2)
|
||
|
||
[*Example [6](#ref-example-6)*: struct Banana { };struct Enigma { operator const Banana(); };struct Alaska { operator Banana&(); };void enigmatic() {typedef const Banana ConstBanana;
|
||
Banana &&banana1 = ConstBanana(); // error Banana &&banana2 = Enigma(); // error Banana &&banana3 = Alaska(); // error}const double& rcd2 = 2; // rcd2 refers to temporary with type const double and value 2.0double&& rrd = 2; // rrd refers to temporary with value 2.0const volatile int cvi = 1;const int& r2 = cvi; // error: cv-qualifier droppedstruct A { operator volatile int&(); } a;const int& r3 = a; // error: cv-qualifier dropped// from result of conversion functiondouble d2 = 1.0;double&& rrd2 = d2; // error: initializer is lvalue of reference-related typestruct X { operator int&(); };int&& rri2 = X(); // error: result of conversion function is// lvalue of reference-related typeint i3 = 2;double&& rrd3 = i3; // rrd3 refers to temporary with value 2.0 â *end example*]
|
||
|
||
In all cases except the last
|
||
(i.e., implicitly converting the initializer expression
|
||
to the referenced type),
|
||
the reference is said to [*bind directly*](#def:bind_directly "9.5.4 References [dcl.init.ref]") to the
|
||
initializer expression[.](#ref-5.sentence-2)
|
||
|
||
[6](#ref-6)
|
||
|
||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/declarations.tex#L6358)
|
||
|
||
[*Note [3](#ref-note-3)*:
|
||
|
||
[[class.temporary]](class.temporary "6.8.7 Temporary objects") describes the lifetime of temporaries bound to references[.](#ref-6.sentence-1)
|
||
|
||
â *end note*]
|
||
|
||
[80)](#footnote-80)[80)](#footnoteref-80)
|
||
|
||
This requires a conversion
|
||
function ([[class.conv.fct]](class.conv.fct "11.4.8.3 Conversion functions")) returning a reference type[.](#footnote-80.sentence-1)
|
||
|
||
### [9.5.5](#list) List-initialization [[dcl.init.list]](dcl.init.list)
|
||
|
||
[1](#list-1)
|
||
|
||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/declarations.tex#L6366)
|
||
|
||
[*List-initialization*](#def:list-initialization "9.5.5 List-initialization [dcl.init.list]") is initialization of an object or reference from a[*braced-init-list*](#nt:braced-init-list "9.5.1 General [dcl.init.general]")[.](#list-1.sentence-1)
|
||
|
||
Such an initializer is called an [*initializer list*](#def:initializer_list), and
|
||
the comma-separated[*initializer-clause*](#nt:initializer-clause "9.5.1 General [dcl.init.general]")*s* of the [*initializer-list*](#nt:initializer-list "9.5.1 General [dcl.init.general]") or[*designated-initializer-clause*](#nt:designated-initializer-clause "9.5.1 General [dcl.init.general]")*s* of the [*designated-initializer-list*](#nt:designated-initializer-list "9.5.1 General [dcl.init.general]") are called the [*elements*](#def:elements) of the initializer list[.](#list-1.sentence-2)
|
||
|
||
An initializer list may be empty[.](#list-1.sentence-3)
|
||
|
||
List-initialization can occur in direct-initialization or copy-initialization contexts;
|
||
list-initialization in a direct-initialization context is called[*direct-list-initialization*](#def:direct-list-initialization "9.5.5 List-initialization [dcl.init.list]") and list-initialization in a
|
||
copy-initialization context is called [*copy-list-initialization*](#def:copy-list-initialization "9.5.5 List-initialization [dcl.init.list]")[.](#list-1.sentence-4)
|
||
|
||
Direct-initialization that is not list-initialization is called[*direct-non-list-initialization*](#def:direct-non-list-initialization "9.5.5 List-initialization [dcl.init.list]")[.](#list-1.sentence-5)
|
||
|
||
[*Note [1](#list-note-1)*:
|
||
|
||
List-initialization can be used
|
||
|
||
- [(1.1)](#list-1.1)
|
||
|
||
as the initializer in a variable definition ([dcl.init]),
|
||
|
||
- [(1.2)](#list-1.2)
|
||
|
||
as the initializer in a [*new-expression*](expr.new#nt:new-expression "7.6.2.8 New [expr.new]") ([[expr.new]](expr.new "7.6.2.8 New")),
|
||
|
||
- [(1.3)](#list-1.3)
|
||
|
||
in a return statement ([[stmt.return]](stmt.return "8.8.4 The return statement")),
|
||
|
||
- [(1.4)](#list-1.4)
|
||
|
||
as a [*for-range-initializer*](stmt.pre#nt:for-range-initializer "8.1 Preamble [stmt.pre]") ([[stmt.iter]](stmt.iter "8.6 Iteration statements")),
|
||
|
||
- [(1.5)](#list-1.5)
|
||
|
||
as a function argument ([[expr.call]](expr.call "7.6.1.3 Function call")),
|
||
|
||
- [(1.6)](#list-1.6)
|
||
|
||
as a template argument ([[temp.arg.nontype]](temp.arg.nontype "13.4.3 Constant template arguments")),
|
||
|
||
- [(1.7)](#list-1.7)
|
||
|
||
as a subscript ([[expr.sub]](expr.sub "7.6.1.2 Subscripting")),
|
||
|
||
- [(1.8)](#list-1.8)
|
||
|
||
as an argument to a constructor invocation ([dcl.init], [[expr.type.conv]](expr.type.conv "7.6.1.4 Explicit type conversion (functional notation)")),
|
||
|
||
- [(1.9)](#list-1.9)
|
||
|
||
as an initializer for a non-static data member ([[class.mem]](class.mem "11.4 Class members")),
|
||
|
||
- [(1.10)](#list-1.10)
|
||
|
||
in a [*mem-initializer*](class.base.init#nt:mem-initializer "11.9.3 Initializing bases and members [class.base.init]") ([[class.base.init]](class.base.init "11.9.3 Initializing bases and members")), or
|
||
|
||
- [(1.11)](#list-1.11)
|
||
|
||
on the right-hand side of an assignment ([[expr.assign]](expr.assign "7.6.19 Assignment and compound assignment operators"))[.](#list-1.sentence-6)
|
||
|
||
[*Example [1](#list-example-1)*: int a = {1};
|
||
std::complex<double> z{1,2};new std::vector<std::string>{"once", "upon", "a", "time"}; // 4 string elements f( {"Nicholas","Annemarie"} ); // pass list of two elementsreturn { "Norah" }; // return list of one elementint* e {}; // initialization to zero / null pointer x = double{1}; // explicitly construct a double std::map<std::string,int> anim = { {"bear",4}, {"cassowary",2}, {"tiger",7} }; â *end example*]
|
||
|
||
â *end note*]
|
||
|
||
[2](#list-2)
|
||
|
||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/declarations.tex#L6413)
|
||
|
||
A constructor is an [*initializer-list constructor*](#def:initializer-list_constructor "9.5.5 List-initialization [dcl.init.list]") if its first parameter is
|
||
of type std::initializer_list<E> or reference tocv std::initializer_list<E> for some type E, and either there are no other
|
||
parameters or else all other parameters have default arguments ([[dcl.fct.default]](dcl.fct.default "9.3.4.7 Default arguments"))[.](#list-2.sentence-1)
|
||
|
||
[*Note [2](#list-note-2)*:
|
||
|
||
Initializer-list constructors are favored over other constructors in
|
||
list-initialization ([[over.match.list]](over.match.list "12.2.2.8 Initialization by list-initialization"))[.](#list-2.sentence-2)
|
||
|
||
Passing an initializer list as the argument
|
||
to the constructor template template<class T> C(T) of a class C does not
|
||
create an initializer-list constructor, because an initializer list argument causes the
|
||
corresponding parameter to be a non-deduced context ([[temp.deduct.call]](temp.deduct.call "13.10.3.2 Deducing template arguments from a function call"))[.](#list-2.sentence-3)
|
||
|
||
â *end note*]
|
||
|
||
The templatestd::initializer_list is not predefined;
|
||
if a standard library declaration ([[initializer.list.syn]](initializer.list.syn "17.11.2 Header <initializer_list> synopsis"), [[std.modules]](std.modules "16.4.2.4 Modules"))
|
||
of std::initializer_list is not reachable from ([[module.reach]](module.reach "10.7 Reachability"))
|
||
a use of std::initializer_list â
|
||
even an implicit use in which the type is not named ([[dcl.spec.auto]](dcl.spec.auto "9.2.9.7 Placeholder type specifiers")) â
|
||
the program is ill-formed[.](#list-2.sentence-4)
|
||
|
||
[3](#list-3)
|
||
|
||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/declarations.tex#L6433)
|
||
|
||
List-initialization of an object or reference of type *cv* T is defined as follows:
|
||
|
||
- [(3.1)](#list-3.1)
|
||
|
||
If the [*braced-init-list*](#nt:braced-init-list "9.5.1 General [dcl.init.general]") contains a [*designated-initializer-list*](#nt:designated-initializer-list "9.5.1 General [dcl.init.general]") andT is not a reference type,T shall be an aggregate class[.](#list-3.1.sentence-1)
|
||
The ordered [*identifier*](lex.name#nt:identifier "5.11 Identifiers [lex.name]")*s* in the [*designator*](#nt:designator "9.5.1 General [dcl.init.general]")*s* of the [*designated-initializer-list*](#nt:designated-initializer-list "9.5.1 General [dcl.init.general]") shall form a subsequence
|
||
of the ordered [*identifier*](lex.name#nt:identifier "5.11 Identifiers [lex.name]")*s* in the direct non-static data members of T[.](#list-3.1.sentence-2)
|
||
Aggregate initialization is performed ([[dcl.init.aggr]](#aggr "9.5.2 Aggregates"))[.](#list-3.1.sentence-3)
|
||
[*Example [2](#list-example-2)*: struct A { int x; int y; int z; };
|
||
A a{.y = 2, .x = 1}; // error: designator order does not match declaration order A b{.x = 1, .z = 2}; // OK, b.y initialized to 0 â *end example*]
|
||
|
||
- [(3.2)](#list-3.2)
|
||
|
||
If T is an aggregate class and the initializer list has a single element
|
||
of type *cv1* U,
|
||
where U is T or a class derived from T,
|
||
the object is initialized from that element (by copy-initialization for
|
||
copy-list-initialization, or by direct-initialization for
|
||
direct-list-initialization)[.](#list-3.2.sentence-1)
|
||
|
||
- [(3.3)](#list-3.3)
|
||
|
||
Otherwise, if T is a character array and the initializer list has a
|
||
single element that is an appropriately-typed [*string-literal*](lex.string#nt:string-literal "5.13.5 String literals [lex.string]") ([[dcl.init.string]](#string "9.5.3 Character arrays")),
|
||
initialization is performed as described in that subclause[.](#list-3.3.sentence-1)
|
||
|
||
- [(3.4)](#list-3.4)
|
||
|
||
Otherwise, if T is an aggregate, aggregate initialization is
|
||
performed ([[dcl.init.aggr]](#aggr "9.5.2 Aggregates"))[.](#list-3.4.sentence-1)
|
||
[*Example [3](#list-example-3)*: double ad[] = { 1, 2.0 }; // OKint ai[] = { 1, 2.0 }; // error: narrowingstruct S2 {int m1; double m2, m3;};
|
||
S2 s21 = { 1, 2, 3.0 }; // OK S2 s22 { 1.0, 2, 3 }; // error: narrowing S2 s23 { }; // OK, default to 0,0,0 â *end example*]
|
||
|
||
- [(3.5)](#list-3.5)
|
||
|
||
Otherwise, if the initializer list has no elements and T is a class type with a
|
||
default constructor, the object is value-initialized[.](#list-3.5.sentence-1)
|
||
|
||
- [(3.6)](#list-3.6)
|
||
|
||
Otherwise, if T is a specialization of std::initializer_list,
|
||
the object is constructed as described below[.](#list-3.6.sentence-1)
|
||
|
||
- [(3.7)](#list-3.7)
|
||
|
||
Otherwise, if T is a class type, constructors are considered[.](#list-3.7.sentence-1)
|
||
The applicable constructors are enumerated and
|
||
the best one is chosen through overload resolution ([[over.match]](over.match "12.2 Overload resolution"), [[over.match.list]](over.match.list "12.2.2.8 Initialization by list-initialization"))[.](#list-3.7.sentence-2)
|
||
If a narrowing
|
||
conversion (see below) is required to convert any of the arguments, the program is
|
||
ill-formed[.](#list-3.7.sentence-3)
|
||
[*Example [4](#list-example-4)*: struct S { S(std::initializer_list<double>); // #1 S(std::initializer_list<int>); // #2 S(std::initializer_list<S>); // #3 S(); // #4// ...};
|
||
S s1 = { 1.0, 2.0, 3.0 }; // invoke #1 S s2 = { 1, 2, 3 }; // invoke #2 S s3{s2}; // invoke #3 (not the copy constructor) S s4 = { }; // invoke #4 â *end example*]
|
||
[*Example [5](#list-example-5)*: struct Map { Map(std::initializer_list<std::pair<std::string,int>>);};
|
||
Map ship = {{"Sophie",14}, {"Surprise",28}}; â *end example*]
|
||
[*Example [6](#list-example-6)*: struct S {// no initializer-list constructors S(int, double, double); // #1 S(); // #2// ...};
|
||
S s1 = { 1, 2, 3.0 }; // OK, invoke #1 S s2 { 1.0, 2, 3 }; // error: narrowing S s3 { }; // OK, invoke #2 â *end example*]
|
||
|
||
- [(3.8)](#list-3.8)
|
||
|
||
Otherwise, if T is an enumeration
|
||
with a fixed underlying type ([[dcl.enum]](dcl.enum "9.8.1 Enumeration declarations")) U,
|
||
the [*initializer-list*](#nt:initializer-list "9.5.1 General [dcl.init.general]") has a single element v of scalar type,v can be implicitly converted to U, and
|
||
the initialization is direct-list-initialization,
|
||
the object is initialized with the value T(v) ([[expr.type.conv]](expr.type.conv "7.6.1.4 Explicit type conversion (functional notation)"));
|
||
if a narrowing conversion is required to convert v to U, the program is ill-formed[.](#list-3.8.sentence-1)
|
||
[*Example [7](#list-example-7)*: enum byte : unsigned char { };
|
||
byte b { 42 }; // OK byte c = { 42 }; // error byte d = byte{ 42 }; // OK; same value as b byte e { -1 }; // errorstruct A { byte b; };
|
||
A a1 = { { 42 } }; // error A a2 = { byte{ 42 } }; // OKvoid f(byte);
|
||
f({ 42 }); // errorenum class Handle : uint32_t { Invalid = 0 };
|
||
Handle h { 42 }; // OK â *end example*]
|
||
|
||
- [(3.9)](#list-3.9)
|
||
|
||
Otherwise, if
|
||
the initializer list
|
||
is not a [*designated-initializer-list*](#nt:designated-initializer-list "9.5.1 General [dcl.init.general]") and
|
||
has a single element of type E and eitherT is not a reference type or its referenced type is
|
||
reference-related to E, the object or reference is initialized
|
||
from that element (by copy-initialization for copy-list-initialization,
|
||
or by direct-initialization for direct-list-initialization);
|
||
if a narrowing conversion (see below) is required
|
||
to convert the element to T, the program is ill-formed[.](#list-3.9.sentence-1)
|
||
[*Example [8](#list-example-8)*: int x1 {2}; // OKint x2 {2.0}; // error: narrowing â *end example*]
|
||
|
||
- [(3.10)](#list-3.10)
|
||
|
||
Otherwise, if T is a reference type, a prvalue is generated[.](#list-3.10.sentence-1)
|
||
The prvalue initializes its result object by copy-list-initialization from the initializer list[.](#list-3.10.sentence-2)
|
||
The prvalue is then used to direct-initialize the reference[.](#list-3.10.sentence-3)
|
||
The type of the prvalue is the type referenced by T,
|
||
unless T is âreference to array of unknown bound of Uâ,
|
||
in which case the type of the prvalue is
|
||
the type of x in the declaration U x[] H,
|
||
where H is the initializer list[.](#list-3.10.sentence-4)
|
||
[*Note [3](#list-note-3)*:
|
||
As usual, the binding will fail and the program is ill-formed if
|
||
the reference type is an lvalue reference to a non-const type[.](#list-3.10.sentence-5)
|
||
â *end note*]
|
||
[*Example [9](#list-example-9)*: struct S { S(std::initializer_list<double>); // #1 S(const std::string&); // #2// ...};const S& r1 = { 1, 2, 3.0 }; // OK, invoke #1const S& r2 { "Spinach" }; // OK, invoke #2 S& r3 = { 1, 2, 3 }; // error: initializer is not an lvalueconst int& i1 = { 1 }; // OKconst int& i2 = { 1.1 }; // error: narrowingconst int (&iar)[2] = { 1, 2 }; // OK, iar is bound to temporary arraystruct A { } a;struct B { explicit B(const A&); };const B& b2{a}; // error: cannot copy-list-initialize B temporary from Astruct C { int x; };
|
||
C&& c = { .x = 1 }; // OK â *end example*]
|
||
|
||
- [(3.11)](#list-3.11)
|
||
|
||
Otherwise, if the initializer list has no elements, the object is
|
||
value-initialized[.](#list-3.11.sentence-1)
|
||
[*Example [10](#list-example-10)*: int** pp {}; // initialized to null pointer â *end example*]
|
||
|
||
- [(3.12)](#list-3.12)
|
||
|
||
Otherwise, the program is ill-formed[.](#list-3.12.sentence-1)
|
||
[*Example [11](#list-example-11)*: struct A { int i; int j; };
|
||
A a1 { 1, 2 }; // aggregate initialization A a2 { 1.2 }; // error: narrowingstruct B { B(std::initializer_list<int>);};
|
||
B b1 { 1, 2 }; // creates initializer_list<int> and calls constructor B b2 { 1, 2.0 }; // error: narrowingstruct C { C(int i, double j);};
|
||
C c1 = { 1, 2.2 }; // calls constructor with arguments (1, 2.2) C c2 = { 1.1, 2 }; // error: narrowingint j { 1 }; // initialize to 1int k { }; // initialize to 0 â *end example*]
|
||
|
||
[4](#list-4)
|
||
|
||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/declarations.tex#L6651)
|
||
|
||
Within the [*initializer-list*](#nt:initializer-list "9.5.1 General [dcl.init.general]") of a [*braced-init-list*](#nt:braced-init-list "9.5.1 General [dcl.init.general]"),
|
||
the [*initializer-clause*](#nt:initializer-clause "9.5.1 General [dcl.init.general]")*s*, including any that result from pack
|
||
expansions ([[temp.variadic]](temp.variadic "13.7.4 Variadic templates")), are evaluated in the order in which they
|
||
appear[.](#list-4.sentence-1)
|
||
|
||
That is, every value computation and side effect associated with a
|
||
given [*initializer-clause*](#nt:initializer-clause "9.5.1 General [dcl.init.general]") is sequenced before every value
|
||
computation and side effect associated with any [*initializer-clause*](#nt:initializer-clause "9.5.1 General [dcl.init.general]") that follows it in the comma-separated list of the [*initializer-list*](#nt:initializer-list "9.5.1 General [dcl.init.general]")[.](#list-4.sentence-2)
|
||
|
||
[*Note [4](#list-note-4)*:
|
||
|
||
This evaluation ordering holds regardless of the semantics of the
|
||
initialization; for example, it applies when the elements of the[*initializer-list*](#nt:initializer-list "9.5.1 General [dcl.init.general]") are interpreted as arguments of a constructor
|
||
call, even though ordinarily there are no sequencing constraints on the
|
||
arguments of a call[.](#list-4.sentence-3)
|
||
|
||
â *end note*]
|
||
|
||
[5](#list-5)
|
||
|
||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/declarations.tex#L6667)
|
||
|
||
An object of type std::initializer_list<E> is constructed from
|
||
an initializer list as if
|
||
the implementation generated and materialized ([[conv.rval]](conv.rval "7.3.5 Temporary materialization conversion"))
|
||
a prvalue of type âarray of N const Eâ,
|
||
where N is the number of elements in the initializer list;
|
||
this is called the initializer list's [*backing array*](#def:array,backing "9.5.5 List-initialization [dcl.init.list]")[.](#list-5.sentence-1)
|
||
|
||
Each element of the backing array is copy-initialized with the
|
||
corresponding element of the initializer list, and thestd::initializer_list<E> object is constructed to refer to that array[.](#list-5.sentence-2)
|
||
|
||
[*Note [5](#list-note-5)*:
|
||
|
||
A constructor or conversion function selected for the copy needs to be
|
||
accessible ([[class.access]](class.access "11.8 Member access control")) in the context of the initializer list[.](#list-5.sentence-3)
|
||
|
||
â *end note*]
|
||
|
||
If a narrowing conversion is required to initialize any of the elements,
|
||
the program is ill-formed[.](#list-5.sentence-4)
|
||
|
||
[*Note [6](#list-note-6)*:
|
||
|
||
Backing arrays are potentially non-unique objects ([[intro.object]](intro.object "6.8.2 Object model"))[.](#list-5.sentence-5)
|
||
|
||
â *end note*]
|
||
|
||
[6](#list-6)
|
||
|
||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/declarations.tex#L6687)
|
||
|
||
The backing array has the same lifetime as any other temporary
|
||
object ([[class.temporary]](class.temporary "6.8.7 Temporary objects")), except that initializing aninitializer_list object from the array extends the lifetime of
|
||
the array exactly like binding a reference to a temporary[.](#list-6.sentence-1)
|
||
|
||
[*Example [12](#list-example-12)*: void f(std::initializer_list<double> il);void g(float x) { f({1, x, 3});}void h() { f({1, 2, 3});}struct A {mutable int i;};void q(std::initializer_list<A>);void r() { q({A{1}, A{2}, A{3}});}
|
||
|
||
The initialization will be implemented in a way roughly equivalent to this:void g(float x) {const double __a[3] = {double{1}, double{x}, double{3}}; // backing array f(std::initializer_list<double>(__a, __a+3));}void h() {static constexpr double __b[3] = {double{1}, double{2}, double{3}}; // backing array f(std::initializer_list<double>(__b, __b+3));}void r() {const A __c[3] = {A{1}, A{2}, A{3}}; // backing array q(std::initializer_list<A>(__c, __c+3));} assuming that the implementation
|
||
can construct an initializer_list object with a pair of pointers, and
|
||
with the understanding that __b does not outlive the call to f[.](#list-6.sentence-2)
|
||
|
||
â *end example*]
|
||
|
||
[*Example [13](#list-example-13)*: typedef std::complex<double> cmplx;
|
||
std::vector<cmplx> v1 = { 1, 2, 3 };
|
||
|
||
void f() { std::vector<cmplx> v2{ 1, 2, 3 };
|
||
std::initializer_list<int> i3 = { 1, 2, 3 };}struct A { std::initializer_list<int> i4;
|
||
A() : i4{ 1, 2, 3 } {} // ill-formed, would create a dangling reference};
|
||
|
||
For v1 and v2, the initializer_list object
|
||
is a parameter in a function call, so the array created for{ 1, 2, 3 } has full-expression lifetime[.](#list-6.sentence-3)
|
||
|
||
For i3, the initializer_list object is a variable,
|
||
so the array persists for the lifetime of the variable[.](#list-6.sentence-4)
|
||
|
||
For i4, the initializer_list object is initialized in
|
||
the constructor's [*ctor-initializer*](class.base.init#nt:ctor-initializer "11.9.3 Initializing bases and members [class.base.init]") as if by binding
|
||
a temporary array to a reference member, so the program is
|
||
ill-formed ([[class.base.init]](class.base.init "11.9.3 Initializing bases and members"))[.](#list-6.sentence-5)
|
||
|
||
â *end example*]
|
||
|
||
[7](#list-7)
|
||
|
||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/declarations.tex#L6758)
|
||
|
||
A [*narrowing conversion*](#def:conversion,narrowing "9.5.5 List-initialization [dcl.init.list]") is an implicit conversion
|
||
|
||
- [(7.1)](#list-7.1)
|
||
|
||
from a floating-point type to an integer type, or
|
||
|
||
- [(7.2)](#list-7.2)
|
||
|
||
from a floating-point type T to another floating-point type
|
||
whose floating-point conversion rank is neither greater than nor equal to
|
||
that of T,
|
||
except where the result of the conversion is a constant expression and
|
||
either its value is finite and the conversion did not overflow, or
|
||
the values before and after the conversion are not finite, or
|
||
|
||
- [(7.3)](#list-7.3)
|
||
|
||
from an integer type or unscoped enumeration type to a floating-point type, except
|
||
where the source is a constant expression and the actual value after conversion will fit
|
||
into the target type and will produce the original value when converted back to the
|
||
original type, or
|
||
|
||
- [(7.4)](#list-7.4)
|
||
|
||
from an integer type or unscoped enumeration type to an integer type that cannot
|
||
represent all the values of the original type, except where
|
||
* [(7.4.1)](#list-7.4.1)
|
||
|
||
the source is a bit-field whose width w is less than that of its type
|
||
(or, for an enumeration type, its underlying type) and
|
||
the target type can represent all the values
|
||
of a hypothetical extended integer type
|
||
with width w and with the same signedness as the original type or
|
||
|
||
* [(7.4.2)](#list-7.4.2)
|
||
|
||
the source is a constant
|
||
expression whose value after integral promotions will fit into the target type, or
|
||
|
||
- [(7.5)](#list-7.5)
|
||
|
||
from a pointer type or a pointer-to-member type to bool[.](#list-7.sentence-1)
|
||
|
||
[*Note [7](#list-note-7)*:
|
||
|
||
As indicated above, such conversions are not allowed at the top level in
|
||
list-initializations[.](#list-7.sentence-2)
|
||
|
||
â *end note*]
|
||
|
||
[*Example [14](#list-example-14)*: int x = 999; // x is not a constant expressionconst int y = 999;const int z = 99;char c1 = x; // OK, though it potentially narrows (in this case, it does narrow)char c2{x}; // error: potentially narrowschar c3{y}; // error: narrows (assuming char is 8 bits)char c4{z}; // OK, no narrowing neededunsigned char uc1 = {5}; // OK, no narrowing neededunsigned char uc2 = {-1}; // error: narrowsunsigned int ui1 = {-1}; // error: narrowssigned int si1 ={ (unsigned int)-1 }; // error: narrowsint ii = {2.0}; // error: narrowsfloat f1 { x }; // error: potentially narrowsfloat f2 { 7 }; // OK, 7 can be exactly represented as a floatbool b = {"meow"}; // error: narrowsint f(int);int a[] = { 2, f(2), f(2.0) }; // OK, the double-to-int conversion is not at the top level â *end example*]
|