-
Notifications
You must be signed in to change notification settings - Fork 0
/
expanded-aggregate-proposal.html
256 lines (218 loc) · 10.6 KB
/
expanded-aggregate-proposal.html
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"
"http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<meta http-equiv="content-type" content="text/html; charset=us-ascii">
<title>Proposal to Expand Aggregates</title>
<meta name="generator" content="Amaya, see http://www.w3.org/Amaya/">
<style type="text/css">
ins { background-color: #A0FFA0 }
del { background-color: #FFA0A0 }
</style>
</head>
<body>
<pre>Document number: Dnnnn
Project: Programming Language C++, Language Evolution Group
Date: 2014-02-02
Reply-to: Daryle Walker <darylew at gmail dot com></pre>
<h1>Proposal to Expand Aggregates</h1>
<h2 id="Ch01">I. Table of Contents</h2>
<ol>
<li><a href="#Ch01">Table of Contents</a></li>
<li><a href="#Ch02">Introduction</a></li>
<li><a href="#Ch03">Motivation and Scope</a></li>
<li><a href="#Ch04">Impact on the Standard</a></li>
<li><a href="#Ch05">Design Decisions</a></li>
<li><a href="#Ch06">Technical Specifications</a></li>
<li><a href="#Ch07">Acknowledgments</a></li>
<li><a href="#Ch08">History</a></li>
<li><a href="#Ch09">References</a></li>
</ol>
<h2 id="Ch02">II. Introduction</h2>
<p>Aggregates are a subset of compound types based on the compound types of C
(arrays, <code>struct</code>s, and <code>union</code>s). This proposal loosens
the restrictions on C-incompatible class types being aggregates in C++.</p>
<h2 id="Ch03">III. Motivation and Scope</h2>
<p>The motivation is to improve "spiritual" parity with C. Some forum
discussions mentioned that certain C++ features that are banned on aggregates
do not conceptually violate the aggregate concept, but are features the C does
not have (and therefore did not have to worry about) and seemingly too
"advanced" for something "primitive" like aggregates.</p>
<h2 id="Ch04">IV. Impact on the Standard</h2>
<p>Loosening restrictions on class types being aggregates requires changes in
the sections pertaining to aggregates, mostly section 8.5.1 [dcl.init.aggr].
The author does not know of any extant implementations.</p>
<h2 id="Ch05">V. Design Decisions</h2>
<h2 id="Ch06">VI. Technical Specifications</h2>
<p>The changes are based off C++ Working Draft Standard N3797. The number for a
new paragraph has a place-holder; the final number, plus moving existing ID
numbers to fit, are to be determined later.</p>
<p>In section 8.5.1 [dcl.init.aggr], modify paragraph 1:</p>
<blockquote>
<p><strong>-1-</strong> An <dfn>aggregate</dfn> is an array or a
<ins>single-source</ins> class (Clause 9) with no user-provided constructors
(12.1) <ins>among it and its base classes (Clause 10) and</ins><del>, no
private or protected</del> <ins>the same access control for any</ins>
non-static data members (Clause 11) <ins>in the source class</ins><del>, no
base classes (Clause 10), and no virtual functions (10.3)</del>. <ins>The
members of an array aggregate are its elements. The members of a class
aggregate are the named non-static data members of its source class,
including the aggregate members of anonymous class members. [<em>Note:</em>
The members of a class aggregate are the ones that could be designated in a
<var>mem-initializer</var> for a theoretical constructor of the source class
(12.6.2). <em>—end note</em>]</ins> </p>
</blockquote>
<p>Specifying what an aggregate's members are here avoids cramming it in the
next paragraph. But the specification makes 8.5.1/5 redundant. The "including
the aggregate members of anonymous class members" means the members of
anonymous unions and, if added later, non-union class types (like the 2011
version of C).</p>
<p>Modify paragraph 2:</p>
<blockquote>
<p><strong>-2-</strong> When an aggregate is initialized by an initializer
list, as specified in 8.5.4, the elements of the initializer list are taken
as initializers for the members of the aggregate, in increasing subscript or
member order. Each member is copy-initialized from the corresponding
<var>initializer-clause</var>. <ins>If the source class or its non-static
data members for an aggregate class are not accessible from the context of
the initializer list, the program is ill-formed. [<em>Example:</em></ins></p>
<blockquote>
<pre><ins>class Z;
Z hello();
class Z {
friend Z hello();
int z;
};
Z hello() {
Z zz{ 1 };
return zz;
}
int main() {
Z yy = { 2 }; <i>// error</i>
Z xx = hello(); <i>// OK</i>
}</ins></pre>
</blockquote>
<p><ins>The non-static data member of aggregate class <code>Z</code> is
<code>private</code>, so only entities that are internal or friendly to
<code>Z</code> may access that member through aggregate initialization.
<em>—end example</em>]</ins> If the <var>initializer-clause</var> is an
expression and a narrowing conversion (8.5.4) is required to convert the
expression, the program is ill-formed. [<em>Note:</em> If an
<var>initializer-clause</var> is itself an initializer list, the member is
list-initialized, which will result in a recursive application of the rules
in this section if the member is an aggregate. <em>—end note</em>]
[<em>Example:</em></p>
<blockquote>
<pre>struct A {
int x;
struct B {
int i;
int j;
} b;
} a = { 1, { 2, 3 } };</pre>
</blockquote>
<p>initializes <code>a.x</code> with 1, <code>a.b.i</code> with 2,
<code>a.b.j</code> with 3. <em>—end example</em>]</p>
</blockquote>
<p>In the root section of Clause 9 [class], add a paragraph before paragraph
7:</p>
<blockquote>
<p><strong>-A-</strong> The <dfn>set of source classes</dfn> for a class
consists of the union of its base classes' sets of source classes plus, when
it declares at least one non-static data member, the class itself. A class is
a <dfn>single-source class</dfn> if its set of source classes either is
empty, contains only the class itself, or contains just the type of a
singularly occurring base-class subobject. [<em>Note:</em> If a single-source
class inherits non-static data members from a base class, then the base class
must be inherited from once and/or have all its inheritances be
<code>virtual</code>. <em>—end note</em>] For a given single-source
class, its <dfn>source class</dfn> is the (sole) class in its set of source
classes, or the single-source class itself if the set is empty.</p>
</blockquote>
<p>Modify paragraph 7:</p>
<blockquote>
<p><strong>-7-</strong> A <dfn>standard-layout class</dfn> is a class that
<ins>has</ins>:</p>
<ul>
<li><del>has</del> no non-static data members of type non-standard-layout
class (or array of such types) or reference,</li>
<li><del>has</del> no virtual functions (10.3) and no virtual base classes
(10.1),</li>
<li><del>has</del> the same access control (Clause 11) for all non-static
data members,</li>
<li><del>has</del> no non-standard-layout base classes,</li>
<li><del>either has no non-static data members in the most derived class
and at most one base class with non-static data members, or has no base
classes with non-static data members</del> <ins>at most one element in
its set of source classes</ins>, and</li>
<li><del>has</del> no base classes of the same type as the first non-static
data member.<sup>110</sup></li>
</ul>
</blockquote>
<p>(Footnote 110 is unchanged.) The main inserted part of the paragraph does
not say "single-source class" since the wording of the main deleted part does
not exclude a data-bearing base class from being (non-virtually) inherited from
more than once. (Also, is the "most derived" phrase in the deleted part an
error, since there is no mention of what happens if a derived class between the
most derived class and the class to be tested for standard layout, excluding
the former and including the latter, is data-bearing?)</p>
<p>In section 12.6.2 [class.base.init], modify paragraph 5:</p>
<blockquote>
<p><strong>-5-</strong> A <var>ctor-initializer</var> may initialize a
variant member of the constructor’s class. If a
<var>ctor-initializer</var> specifies more than one
<var>mem-initializer</var> for the same member or for the same base class,
the <var>ctor-initializer</var> is ill-formed. <ins>If a
<var>ctor-initializer</var> specifies a <var>mem-initializer</var> for an
aggregate direct base class that derives from a virtual base class with
non-static data members and a separate <var>mem-initializer</var> for an
aggregate base class that derives from or is the same virtual base class, the
<var>ctor-initializer</var> is ill-formed.</ins></p>
</blockquote>
<p>Modify paragraph 7:</p>
<blockquote>
<p><strong>-7-</strong> The <var>expression-list</var> or
<var>braced-init-list</var> in a <var>mem-initializer</var> is used to
initialize the designated subobject (or, in the case of a delegating
constructor, the complete class object) according to the initialization rules
of 8.5 for direct-initialization. [<em>Example:</em></p>
<blockquote>
<pre>struct B1 { B1(int); /* ... */ };
struct B2 { B2(int); /* ... */ };
struct D : B1, B2 {
D(int);
B1 b;
const int c;
};
D::D(int a) : B2(a+1), B1(a+2), c(a+3), b(a+4)
{ /* ... */ }
D d(10);</pre>
</blockquote>
<p><em>—end example</em>] The initialization performed by each
<var>mem-initializer</var> constitutes a full-expression. Any expression in a
<var>mem-initializer</var> is evaluated as part of the full-expression that
performs the initialization. A <var>mem-initializer</var> where the
<var>mem-initializer-id</var> denotes <ins>either</ins> a virtual base class
<ins>or an aggregate direct base class deriving from a virtual base class
with non-static data members</ins> is ignored during execution of a
constructor of any class that is not the most derived class.</p>
</blockquote>
<p>A (non-aggregate) class specifying an aggregate for a direct base class,
where that base class inherits (directly or indirectly) virtually from its
source class, provides a new path for a virtual class subobject to be
initialized within a constructor, so it must not be evaluated when the
constructor's class is not the most derived class. (The direct base class has
no potentially-skipped initialization outside the virtual base class, otherwise
it could not be an aggregate.)</p>
<h2 id="Ch07">VII. Acknowledgments</h2>
<h2 id="Ch08">VIII. History</h2>
<h2 id="Ch09">IX. References</h2>
<ul>
<li>"<a name="Relaxing" id="Relaxing"
href="https://groups.google.com/a/isocpp.org/d/topic/std-proposals/77IY0cAlYR8/discussion">Relaxing
constraints on base class for aggregate types</a>" post and replies by
Corentin Schreiber <i>et al.</i>, starting on 15 Dec 2013 (Sunday) at
05:34:34.</li>
</ul>
</body>
</html>