forked from HowardHinnant/papers
-
Notifications
You must be signed in to change notification settings - Fork 5
/
more-perfect-forwarding.html
148 lines (136 loc) · 5.86 KB
/
more-perfect-forwarding.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
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"
"http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<title>LWG 2089, Towards more perfect forwarding</title>
<style>
p {text-align:justify}
li {text-align:justify}
blockquote.note
{
background-color:#E0E0E0;
padding-left: 15px;
padding-right: 15px;
padding-top: 1px;
padding-bottom: 1px;
}
ins {color:#00A000}
del {color:#A00000}
</style>
</head>
<body>
<address align=right>
Document number: D????
<br/>
<br/>
<a href="mailto:[email protected]">Ville Voutilainen</a><br/>
2015-04-07<br/>
</address>
<hr/>
<h1 align=center>LWG 2089, Towards more perfect forwarding</h1>
<h2>Abstract</h2>
<p>It has been known for quite some time that the library object
factories (<code>make_unique</code>, <code>make_shared</code>,
<code>allocator::construct</code>) don't
handle aggregates well, due to the factory functions requiring
a parentheses-expression. There seems to be a simple and elegant fix that
provides aggregate support without any loss of current functionality;
(see the proposed resolution of <a href="http://cplusplus.github.io/LWG/lwg-active.html#2089">LWG 2089</a>) making such factories provide both
braced-initialization and direct-initialization via a trait check
for <code>is_constructible</code>. This paper seeks to solicit EWG feedback
on whether the proposed fix is the right solution going forward, or whether
EWG thinks there are better alternatives.
<a name="Introduction"></a><h2>Introduction</h2>
<p>
Currently, <code>allocator::construct</code> is specified as follows:
</p>
<blockquote><pre>
template <class U, class... Args&>
void construct(U* p, Args&&... args);
Effects: ::new((void *)p) U(std::forward<Args>(args)...)
</pre></blockquote>
<p>
This doesn't handle an aggregate that is initializable with
<code>U{std::forward<Args>(args)...}</code>. Same problem
applies to <code>make_shared</code> and <code>make_unique</code>.
LWG 2089 proposes a fix that allows all the current code to work,
and allows aggregates to work, too.
</p>
<p>
The gist of the proposed library fix is simple:
</p>
<p>
<ul>
<li>if <code>is_constructible_v<TargetType, Args...></code>, use direct-nonlist-initialization</li>
<li>otherwise, use brace-initialization.</li>
</ul>
</p>
<p>
The first bullet will check whether there's a constructor that can construct from the given arguments. An aggregate will not have such a constructor. Non-aggregates will hit the first bullet, aggregates will hit the second bullet.
</p>
<a name="SimpleSuggestion"></a><h2>Simple suggestion</h2>
<p>
The proposed resolution for LWG 2089
<ul>
<li>allows aggregates to work with the library factories.</li>
<li>adds no run-time overhead.</li>
<li>doesn't break significant amounts of code (modulo expression SFINAE cases that
are broken by any change, and are unlikely to be truly broken, since
an overload that wasn't chosen previously because it wouldn't work will now
be chosen and will now work. Also modulo cases where a user class befriended
a library factory function so that the library factory function would've
been able to invoke a private constructor, but I don't think the library
specification guarantees that the library will not use internal helpers
to do its work, so such techniques were never really guaranteed to work).
<li>is unlikely to significantly increase build times.</li>
<li>is between trivial and easy to implement.</li>
<li>requires no language changes.</li>
</ul>
</p>
<p>
Since it's somewhat unlikely that we will devise some magic-forwarding
language facility, it certainly looks like the list above means the proposed
resolution of LWG 2089 is an improvement, and
we should just encourage LEWG/LWG to go forward with the proposed resolution
of LWG 2089, keeping in mind that it needs to be applied to at least all of
<code>allocator::construct</code>, <code>allocator_traits::construct</code>, <code>make_unique</code> and
<code>make_shared</code>. (<code>uninitialized_copy</code>? <code>uninitialized_fill</code>?
Anything else? I can't find any others,
<code>EmplaceConstructible</code> is specified in terms of
<code>allocator::construct</code>, so emplace cases will Just Work).
Note that <code>std::experimental::optional</code> has a similar issue
in its in-place constructor, so that should be considered separately,
as it's in a different document.
</p>
<a name="IsThatAll"></a><h2>Is that all?</h2>
<p>
Well, no. One of the reasons this paper is an EWG paper is that while
the proposed resolution to LWG 2089 can fix the problem for library
factories, and library vendors will certainly have little trouble
implementing such a fix, user types don't really have a non-expert
solution they can use. Teaching users that they need to eg. (*scary part begins*)delegate
to a static member function template of a class template that takes a non-type
bool parameter, fully specialize that class template for the false case,
and dispatch on the result of <code>is_constructible</code> (or dispatch
to tagged overloads, with <code>true_type</code> and <code>false_type</code>)(*scary part ends*) is a fairly
significant teachability issue. I don't personally look forward to teaching
the bit marked with the *scary* markers - and I don't blame anyone who
feels the same.
</p>
<p>
Some strawman ideas how to provide users with some help:
</p>
<p>
<ul>
<li>Invent some better forwarding syntax that is aware of whether the
intended initialization is to use braces or not (I don't know how; the
syntax space is crowded)</li>
<li>Add a library helper that will perform the initialization in the
"right way" depending on <code>is_constructible</code> - in other words,
expose parts of the implementation technique that library vendors are
likely going to use, as a simple library function.</li>
<li>Other ways? How about allowing aggregates to be initialized with
direct-non-list-initialization syntax?</li>
</p>
</body>
</html>