From Jason Turner

[dcl.init.ref]

Diff to HTML by rtfpessoa

Files changed (1) hide show
  1. tmp/tmpe4g6xyg0/{from.md → to.md} +36 -30
tmp/tmpe4g6xyg0/{from.md → to.md} RENAMED
@@ -25,11 +25,11 @@ void f() {
25
 
26
  A reference cannot be changed to refer to another object after
27
  initialization.
28
 
29
  [*Note 1*: Assignment to a reference assigns to the object referred to
30
- by the reference [[expr.ass]]. — *end note*]
31
 
32
  Argument passing [[expr.call]] and function value return [[stmt.return]]
33
  are initializations.
34
 
35
  The initializer can be omitted for a reference only in a parameter
@@ -102,23 +102,25 @@ A reference to type “*cv1* `T1`” is initialized by an expression of type
102
  double& rd3 = i; // error: type mismatch and reference not const
103
  ```
104
 
105
  — *end example*]
106
  - Otherwise, if the initializer expression
107
- - is an rvalue (but not a bit-field) or function lvalue and “*cv1*
108
- `T1`” is reference-compatible with “*cv2* `T2`”, or
109
  - has a class type (i.e., `T2` is a class type), where `T1` is not
110
- reference-related to `T2`, and can be converted to an rvalue or
111
- function lvalue of type “*cv3* `T3`”, where “*cv1* `T1`” is
112
- reference-compatible with “*cv3* `T3`” (see  [[over.match.ref]]),
 
113
 
114
  then the initializer expression in the first case and the converted
115
  expression in the second case is called the converted initializer. If
116
- the converted initializer is a prvalue, its type `T4` is adjusted to
117
- type “*cv1* `T4` [[conv.qual]] and the temporary materialization
118
- conversion [[conv.rval]] is applied. In any case, the reference binds
119
- to the resulting glvalue (or to an appropriate base class subobject).
 
120
  \[*Example 5*:
121
  ``` cpp
122
  struct A { };
123
  struct B : A { } b;
124
  extern B f();
@@ -130,37 +132,40 @@ A reference to type “*cv1* `T1`” is initialized by an expression of type
130
  } x;
131
  const A& r = x; // binds to the A subobject of the result of the conversion
132
  int i2 = 42;
133
  int&& rri = static_cast<int&&>(i2); // binds directly to i2
134
  B&& rrb = x; // binds directly to the result of operator B
 
 
 
 
 
 
 
 
 
 
 
135
  ```
136
 
137
  — *end example*]
138
- - Otherwise:
139
- - If `T1` or `T2` is a class type and `T1` is not reference-related to
140
- `T2`, user-defined conversions are considered using the rules for
141
- copy-initialization of an object of type “*cv1* `T1`” by
142
- user-defined conversion
143
  [[dcl.init]], [[over.match.copy]], [[over.match.conv]]; the program
144
  is ill-formed if the corresponding non-reference copy-initialization
145
- would be ill-formed. The result of the call to the conversion
146
  function, as described for the non-reference copy-initialization, is
147
- then used to direct-initialize the reference. For this
148
- direct-initialization, user-defined conversions are not considered.
 
149
  - Otherwise, the initializer expression is implicitly converted to a
150
  prvalue of type “`T1`”. The temporary materialization conversion is
151
  applied, considering the type of the prvalue to be “*cv1* `T1`”, and
152
  the reference is bound to the result.
153
 
154
- If `T1` is reference-related to `T2`:
155
- - *cv1* shall be the same cv-qualification as, or greater
156
- cv-qualification than, *cv2*; and
157
- - if the reference is an rvalue reference, the initializer expression
158
- shall not be an lvalue. \[*Note 3*: This can be affected by whether
159
- the initializer expression is move-eligible
160
- [[expr.prim.id.unqual]]. — *end note*]
161
-
162
  \[*Example 6*:
163
  ``` cpp
164
  struct Banana { };
165
  struct Enigma { operator const Banana(); };
166
  struct Alaska { operator Banana&(); };
@@ -169,29 +174,30 @@ A reference to type “*cv1* `T1`” is initialized by an expression of type
169
  Banana &&banana1 = ConstBanana(); // error
170
  Banana &&banana2 = Enigma(); // error
171
  Banana &&banana3 = Alaska(); // error
172
  }
173
 
174
- const double& rcd2 = 2; // rcd2 refers to temporary with value 2.0
175
  double&& rrd = 2; // rrd refers to temporary with value 2.0
176
  const volatile int cvi = 1;
177
  const int& r2 = cvi; // error: cv-qualifier dropped
178
  struct A { operator volatile int&(); } a;
179
  const int& r3 = a; // error: cv-qualifier dropped
180
  // from result of conversion function
181
  double d2 = 1.0;
182
- double&& rrd2 = d2; // error: initializer is lvalue of related type
183
  struct X { operator int&(); };
184
- int&& rri2 = X(); // error: result of conversion function is lvalue of related type
 
185
  int i3 = 2;
186
  double&& rrd3 = i3; // rrd3 refers to temporary with value 2.0
187
  ```
188
 
189
  — *end example*]
190
 
191
  In all cases except the last (i.e., implicitly converting the
192
  initializer expression to the referenced type), the reference is said to
193
  *bind directly* to the initializer expression.
194
 
195
- [*Note 4*: [[class.temporary]] describes the lifetime of temporaries
196
  bound to references. — *end note*]
197
 
 
25
 
26
  A reference cannot be changed to refer to another object after
27
  initialization.
28
 
29
  [*Note 1*: Assignment to a reference assigns to the object referred to
30
+ by the reference [[expr.assign]]. — *end note*]
31
 
32
  Argument passing [[expr.call]] and function value return [[stmt.return]]
33
  are initializations.
34
 
35
  The initializer can be omitted for a reference only in a parameter
 
102
  double& rd3 = i; // error: type mismatch and reference not const
103
  ```
104
 
105
  — *end example*]
106
  - Otherwise, if the initializer expression
107
+ - is an rvalue (but not a bit-field) or an lvalue of function type and
108
+ “*cv1* `T1`” is reference-compatible with “*cv2* `T2`”, or
109
  - has a class type (i.e., `T2` is a class type), where `T1` is not
110
+ reference-related to `T2`, and can be converted to an rvalue of type
111
+ “*cv3* `T3`” or an lvalue of function type “*cv3* `T3`”, where
112
+ “*cv1* `T1`” is reference-compatible with “*cv3* `T3`” (see 
113
+ [[over.match.ref]]),
114
 
115
  then the initializer expression in the first case and the converted
116
  expression in the second case is called the converted initializer. If
117
+ the converted initializer is a prvalue, let its type be denoted by
118
+ `T4`; the temporary materialization conversion [[conv.rval]] is
119
+ applied, considering the type of the prvalue to be “*cv1* `T4`”
120
+ [[conv.qual]]. In any case, the reference binds to the resulting
121
+ glvalue (or to an appropriate base class subobject).
122
  \[*Example 5*:
123
  ``` cpp
124
  struct A { };
125
  struct B : A { } b;
126
  extern B f();
 
132
  } x;
133
  const A& r = x; // binds to the A subobject of the result of the conversion
134
  int i2 = 42;
135
  int&& rri = static_cast<int&&>(i2); // binds directly to i2
136
  B&& rrb = x; // binds directly to the result of operator B
137
+
138
+ constexpr int f() {
139
+ const int &x = 42;
140
+ const_cast<int &>(x) = 1; // undefined behavior
141
+ return x;
142
+ }
143
+ constexpr int z = f(); // error: not a constant expression
144
+
145
+ typedef int *AP[3]; // array of 3 pointer to int
146
+ typedef const int *const ACPC[3]; // array of 3 const pointer to const int
147
+ ACPC &&r = AP{}; // binds directly
148
  ```
149
 
150
  — *end example*]
151
+ - Otherwise, `T1` shall not be reference-related to `T2`.
152
+ - If `T1` or `T2` is a class type, user-defined conversions are
153
+ considered using the rules for copy-initialization of an object of
154
+ type “*cv1* `T1`” by user-defined conversion
 
155
  [[dcl.init]], [[over.match.copy]], [[over.match.conv]]; the program
156
  is ill-formed if the corresponding non-reference copy-initialization
157
+ would be ill-formed. The result E of the call to the conversion
158
  function, as described for the non-reference copy-initialization, is
159
+ then used to direct-initialize the reference using the form `(E)`.
160
+ For this direct-initialization, user-defined conversions are not
161
+ considered.
162
  - Otherwise, the initializer expression is implicitly converted to a
163
  prvalue of type “`T1`”. The temporary materialization conversion is
164
  applied, considering the type of the prvalue to be “*cv1* `T1`”, and
165
  the reference is bound to the result.
166
 
 
 
 
 
 
 
 
 
167
  \[*Example 6*:
168
  ``` cpp
169
  struct Banana { };
170
  struct Enigma { operator const Banana(); };
171
  struct Alaska { operator Banana&(); };
 
174
  Banana &&banana1 = ConstBanana(); // error
175
  Banana &&banana2 = Enigma(); // error
176
  Banana &&banana3 = Alaska(); // error
177
  }
178
 
179
+ const double& rcd2 = 2; // rcd2 refers to temporary with type const double and value 2.0
180
  double&& rrd = 2; // rrd refers to temporary with value 2.0
181
  const volatile int cvi = 1;
182
  const int& r2 = cvi; // error: cv-qualifier dropped
183
  struct A { operator volatile int&(); } a;
184
  const int& r3 = a; // error: cv-qualifier dropped
185
  // from result of conversion function
186
  double d2 = 1.0;
187
+ double&& rrd2 = d2; // error: initializer is lvalue of reference-related type
188
  struct X { operator int&(); };
189
+ int&& rri2 = X(); // error: result of conversion function is
190
+ // lvalue of reference-related type
191
  int i3 = 2;
192
  double&& rrd3 = i3; // rrd3 refers to temporary with value 2.0
193
  ```
194
 
195
  — *end example*]
196
 
197
  In all cases except the last (i.e., implicitly converting the
198
  initializer expression to the referenced type), the reference is said to
199
  *bind directly* to the initializer expression.
200
 
201
+ [*Note 3*: [[class.temporary]] describes the lifetime of temporaries
202
  bound to references. — *end note*]
203