-
Notifications
You must be signed in to change notification settings - Fork 0
/
std-xform-proposal.html
426 lines (366 loc) · 17.4 KB
/
std-xform-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
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
<!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 Add Standard-Defined Transformation Type-Traits</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++, Library Evolution Group
Date: 2014-01-20
Reply-to: Daryle Walker <darylew at gmail dot com></pre>
<h1>Proposal to Add Standard-Defined Transformation Type-Traits</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>This proposal aims to add several type translations that are in the
Standard, but do not have a corresponding transformation type-trait.</p>
<h2 id="Ch03">III. Motivation and Scope</h2>
<p>There are several type mappings within the Standard that currently do not
have a transformation type-trait class. User-defined mappings are possible, but
fraught with peril since extended integer or other implementation-defined types
may be involved, requiring exhaustive non-portable specifications for said
manual implementations.</p>
<p>An example are the four character-oriented integer types (<code>char</code>,
<code>char16_t</code>, <code>char32_t</code>, and <code>wchar_t</code>). The
<code>char16_t</code> and <code>char32_t</code> types have their underlying
types explicitly specified (whatever <code>uint_least16_t</code> and
<code>uint_least32_t</code> name). The equivalent of an underlying type for
<code>char</code> can be checked with a preprocessor constants against
<code>signed char</code> or <code>unsigned char</code>. But the underlying type
of <code>wchar_t</code> must be exhaustively searched for, which may still be
wrong if multiple integer types share the same attributes (like
<code>int</code> and <code>long</code> on common 32-bit systems). The
implementation has to know all of these, and a common interface would aid
generic programming, so they can be grouped with the existing
<code>underlying_type</code> trait.</p>
<p>Another example is type promotion. Its purpose is to lengthen variables
shorter than a processor register to a register length for speed, since extra
instructions are needed for variables that fill part of a register. In the old
days, it was easy to guess what the mappings were (anything below
<code>int</code> or <code>double</code> goes to those, respectively). But drift
from <code>int</code>/<code>double</code> representing a register (<i>e.g.</i>
keeping <code>int</code> 32 bits in a 64-bit world for "backwards
compatibility"), extended integer types, and interpreting the size of
enumeration types (pre-<code>underlying_type</code>) complicates complete
solutions. As in the first example, the implementation has to know this
already, so why not let the implementation provide the user access.</p>
<p>The last example expands the "C++ as a better C" workflow. The variable
argument facility in C passed most types as-is. The exceptions were types that
were subject to promotion and function/array-to-pointer decay. C++ adds a new
complication in that not all non-POD (plain old data) types may be supported
through variable-argument passing. (C doesn't have non-POD types.) Whether a
class type is usable through the <code>...</code> argument is hidden by the
implementation; there is no way to check without writing it and waiting for
compile-time (or worse, run-time) errors. A trait class can be written to
handle any type through variable-argument passing, whether the type goes
through unchanged, gets decayed/promoted, or is forbidden. A unified interface
helps when the type in question is a template argument; a simple use of a
type-trait with the template argument type instead of manually special-casing
for promoted types, array types, incompatible class types, and decoding type
aliases.</p>
<p>The idea for the proposal was from needing to know the type promotion
mappings, in order to implement the C-level variable-argument mappings. I
realized it was a better idea to add both to the Standard, plus any others that
are missing.</p>
<p>The transformation for type promotion is present in the Type-Traits library
within the Boost libraries.</p>
<h2 id="Ch04">IV. Impact on the Standard</h2>
<p>The proposal modifies a class template and adds three more (and their
corresponding type-alias templates, when applicable). The implementation should
work with current language features, using knowledge it already needs.</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.</p>
<p>Modify section 20.10.2 [meta.type.synop]:</p>
<blockquote>
<pre>namespace std {
<i>// 20.10.3, helper class:</i>
template <class T, T v> struct integral_constant;
typedef integral_constant<bool, true> true_type;
typedef integral_constant<bool, false> false_type;
<i>// 20.10.4.1, primary type categories:</i>
template <class T> struct is_void;
template <class T> struct is_null_pointer;
template <class T> struct is_integral;
template <class T> struct is_floating_point;
template <class T> struct is_array;
template <class T> struct is_pointer;
template <class T> struct is_lvalue_reference;
template <class T> struct is_rvalue_reference;
template <class T> struct is_member_object_pointer;
template <class T> struct is_member_function_pointer;
template <class T> struct is_enum;
template <class T> struct is_union;
template <class T> struct is_class;
template <class T> struct is_function;
<i>// 20.10.4.2, composite type categories:</i>
template <class T> struct is_reference;
template <class T> struct is_arithmetic;
template <class T> struct is_fundamental;
template <class T> struct is_object;
template <class T> struct is_scalar;
template <class T> struct is_compound;
template <class T> struct is_member_pointer;
<i>// 20.10.4.3, type properties:</i>
template <class T> struct is_const;
template <class T> struct is_volatile;
template <class T> struct is_trivial;
template <class T> struct is_trivially_copyable;
template <class T> struct is_standard_layout;
template <class T> struct is_pod;
template <class T> struct is_literal_type;
template <class T> struct is_empty;
template <class T> struct is_polymorphic;
template <class T> struct is_abstract;
template <class T> struct is_signed;
template <class T> struct is_unsigned;
template <class T, class... Args> struct is_constructible;
template <class T> struct is_default_constructible;
template <class T> struct is_copy_constructible;
template <class T> struct is_move_constructible;
template <class T, class U> struct is_assignable;
template <class T> struct is_copy_assignable;
template <class T> struct is_move_assignable;
template <class T> struct is_destructible;
template <class T, class... Args> struct is_trivially_constructible;
template <class T> struct is_trivially_default_constructible;
template <class T> struct is_trivially_copy_constructible;
template <class T> struct is_trivially_move_constructible;
template <class T, class U> struct is_trivially_assignable;
template <class T> struct is_trivially_copy_assignable;
template <class T> struct is_trivially_move_assignable;
template <class T> struct is_trivially_destructible;
template <class T, class... Args> struct is_nothrow_constructible;
template <class T> struct is_nothrow_default_constructible;
template <class T> struct is_nothrow_copy_constructible;
template <class T> struct is_nothrow_move_constructible;
template <class T, class U> struct is_nothrow_assignable;
template <class T> struct is_nothrow_copy_assignable;
template <class T> struct is_nothrow_move_assignable;
template <class T> struct is_nothrow_destructible;
template <class T> struct has_virtual_destructor;
<ins>template <class T> struct has_vararg_type;</ins>
<i>// 20.10.5, type property queries:</i>
template <class T> struct alignment_of;
template <class T> struct rank;
template <class T, unsigned I = 0> struct extent;
<i>// 20.10.6, type relations:</i>
template <class T, class U> struct is_same;
template <class Base, class Derived> struct is_base_of;
template <class From, class To> struct is_convertible;
<i>// 20.10.7.1, const-volatile modifications:</i>
template <class T> struct remove_const;
template <class T> struct remove_volatile;
template <class T> struct remove_cv;
template <class T> struct add_const;
template <class T> struct add_volatile;
template <class T> struct add_cv;
template <class T>
using remove_const_t = typename remove_const<T>::type;
template <class T>
using remove_volatile_t = typename remove_volatile<T>::type;
template <class T>
using remove_cv_t = typename remove_cv<T>::type;
template <class T>
using add_const_t = typename add_const<T>::type;
template <class T>
using add_volatile_t = typename add_volatile<T>::type;
template <class T>
using add_cv_t = typename add_cv<T>::type;
<i>// 20.10.7.2, reference modifications:</i>
template <class T> struct remove_reference;
template <class T> struct add_lvalue_reference;
template <class T> struct add_rvalue_reference;
template <class T>
using remove_reference_t = typename remove_reference<T>::type;
template <class T>
using add_lvalue_reference_t = typename add_lvalue_reference<T>::type;
template <class T>
using add_rvalue_reference_t = typename add_rvalue_reference<T>::type;
<i>// 20.10.7.3, sign modifications:</i>
template <class T> struct make_signed;
template <class T> struct make_unsigned;
template <class T>
using make_signed_t = typename make_signed<T>::type;
template <class T>
using make_unsigned_t = typename make_unsigned<T>::type;
<i>// 20.10.7.4, array modifications:</i>
template <class T> struct remove_extent;
template <class T> struct remove_all_extents;
template <class T>
using remove_extent_t = typename remove_extent<T>::type;
template <class T>
using remove_all_extents_t = typename remove_all_extents<T>::type;
<i>// 20.10.7.5, pointer modifications:</i>
template <class T> struct remove_pointer;
template <class T> struct add_pointer;
template <class T>
using remove_pointer_t = typename remove_pointer<T>::type;
template <class T>
using add_pointer_t = typename add_pointer<T>::type;
<i>// 20.10.7.6, other transformations:</i>
template <std::size_t Len,
std::size_t Align = default-alignment> <i>// see 20.10.7.6</i>
struct aligned_storage;
template <std::size_t Len, class... Types> struct aligned_union;
template <class T> struct decay;
template <bool, class T = void> struct enable_if;
template <bool, class T, class F> struct conditional;
template <class... T> struct common_type;
template <class T> struct underlying_type;
template <class> class result_of; // not defined
template <class F, class... ArgTypes> class result_of<F(ArgTypes...)>;
<ins>template <class T> struct promote;</ins>
<ins>template <class T> struct vararg_type;</ins>
template <std::size_t Len,
std::size_t Align = default-alignment > <i>// see 20.10.7.6</i>
using aligned_storage_t = typename aligned_storage<Len,Align>::type;
template <std::size_t Len, class... Types>
using aligned_union_t = typename aligned_union<Len,Types...>::type;
template <class T>
using decay_t = typename decay<T>::type;
template <bool b, class T = void>
using enable_if_t = typename enable_if<b,T>::type;
template <bool b, class T, class F>
using conditional_t = typename conditional<b,T,F>::type;
template <class... T>
using common_type_t = typename common_type<T...>::type;
template <class T>
using underlying_type_t = typename underlying_type<T>::type;
template <class T>
using result_of_t = typename result_of<T>::type;
<ins>template <class T>
using promote_t = typename promote<T>::type;
template <class T>
using vararg_type_t = typename vararg_type<T>::type;
</ins>} <i>// namespace std</i></pre>
</blockquote>
<p>In section 20.10.4.3 [meta.unary.prop], append a row to Table 49:</p>
<blockquote>
<table border="1">
<caption>Addition to: Table 49 — Type property predicates
(continued)</caption>
<thead>
<tr>
<th>Template</th>
<th>Condition</th>
<th>Preconditions</th>
</tr>
</thead>
<tbody>
<tr>
<td><pre>template <class T>
struct has_vararg_type;</pre>
</td>
<td><code>vararg_type<T></code> (20.10.7.6) has a member type
named <code>type</code>.</td>
<td></td>
</tr>
</tbody>
</table>
</blockquote>
<p><u>Author's Note:</u> Would depending only on <abbr>SFINAE</abbr> upon
<code>vararg_type</code> be better?</p>
<p>In section 20.10.7.6 [meta.trans.other], modify the seventh row of Table
57:</p>
<blockquote>
<table border="1">
<caption>Modification to: Table 57 — Other transformations
(continued)</caption>
<thead>
<tr>
<th>Template</th>
<th>Condition</th>
<th>Comments</th>
</tr>
</thead>
<tbody>
<tr>
<td><pre>template <class T>
struct underlying_type;</pre>
</td>
<td><p><code>T</code> shall be <ins>either</ins> an enumeration type
(7.2) <ins>or one of the following integer types: <code>char</code>,
<code>char16_t</code>, <code>char32_t</code>, or
<code>wchar_t</code></ins>.</p>
</td>
<td><p>The member typedef <code>type</code> shall name the underlying
type of <code>T</code> <ins>(3.9.1, 7.2)</ins>. <ins>When
<code>T</code> names <code>char</code>, <code>type</code> shall alias
<code>signed char</code> if a <code>char</code> object can hold
negative values, otherwise <code>unsigned char</code>.</ins></p>
</td>
</tr>
</tbody>
</table>
</blockquote>
<p><u>Author's Note:</u> Should <code>char</code> be removed? (Unlike the other
built-in character types, the term <var>underlying type</var> is not used among
the narrow character types.) Should <code>bool</code> be added? (There is no
mention if it has to shadow another integer type.)</p>
<p>And append two rows to that same table:</p>
<blockquote>
<table border="1">
<caption>Addition to: Table 57 — Other transformations
(continued)</caption>
<thead>
<tr>
<th>Template</th>
<th>Condition</th>
<th>Comments</th>
</tr>
</thead>
<tbody>
<tr>
<td><pre>template <class T>
struct promote;</pre>
</td>
<td><code>T</code> shall be either an arithmetic or enumeration
type.</td>
<td>If <code>T</code> names a type subject to either integral promotion
(4.5) or floating point promotion (4.6), then the member typedef
<code>type</code> shall name the promoted type. Otherwise,
<code>type</code> shall name the same type as <code>T</code>.</td>
</tr>
<tr>
<td><pre>template <class T>
struct vararg_type;</pre>
</td>
<td></td>
<td>The member typedef <code>type</code> shall name the type a
receiving function would use with <code>va_arg</code> to obtain an
argument of type <code>T</code> that passed to the function without a
parameter. If the translation process (5.2.2) upon <code>T</code>
would either be ill-formed or involve a class type with a non-trivial
copy-constructor, move-constructor, or destructor that lacks
conditional support, there shall be no member <code>type</code>.</td>
</tr>
</tbody>
</table>
</blockquote>
<h2 id="Ch07">VII. Acknowledgments</h2>
<h2 id="Ch08">VIII. History</h2>
<h2 id="Ch09">IX. References</h2>
<ul>
<li>"promote - 1.55.0"; Boost.org. <a
href="http://www.boost.org/doc/libs/1_55_0/libs/type_traits/doc/html/boost_typetraits/reference/promote.html">www.boost.org/doc/libs/1_55_0/libs/type_traits/doc/html/boost_typetraits/reference/promote.html</a></li>
</ul>
</body>
</html>