2
2
3
3
$(D_S Variadic Templates,
4
4
5
+ $(HEADERNAV_TOC)
6
+
5
7
$(P The problem statement is simple: write a function that
6
8
takes an arbitrary number of values of arbitrary types,
7
9
and print those values out one per line in a manner
@@ -22,15 +24,14 @@ $(CONSOLE
22
24
)
23
25
24
26
$(P We'll explore how this can
25
- be done in standard C++, followed by doing it using
26
- the proposed variadic template C++ extension.
27
+ be done in C++.
27
28
Then, we'll do it the various ways the D programming
28
29
language makes possible.
29
30
)
30
31
31
- $(H3 C++ Solutions)
32
+ $(H2 $(LNAME2 cpp-solutions, C++ Solutions) )
32
33
33
- $(H4 The Standard C++ Solution)
34
+ $(H3 The Overload Solution)
34
35
35
36
$(P The straightforward way to do this in standard C++
36
37
is to use a series of function templates, one for
@@ -97,12 +98,9 @@ template<class T1, class T2, class T3> void print(T1 a1, T2 a2, T3 a3)
97
98
compilation.
98
99
)
99
100
100
- $(H4 The C++ Extension Solution )
101
+ $(H3 C++ Variadic Templates )
101
102
102
- $(P Douglas Gregor has proposed a
103
- variadic template scheme [1]
104
- for C++ that solves these problems.
105
- The result looks like:
103
+ $(P C++11 supports variadic templates:
106
104
)
107
105
108
106
$(CCODE
@@ -120,17 +118,11 @@ template<class T, class... U> void print(T a1, U... an)
120
118
$(P It uses recursive function template instantiation
121
119
to pick off the arguments one by one.
122
120
A specialization with no arguments ends the recursion.
123
- It's a neat and tidy solution, but with one glaring problem:
124
- it's a proposed extension, which means it isn't part
125
- of the C++ standard, may not get into the C++ standard
126
- in its current form, may not get into the standard
127
- in any form, and even if it does, it may be many, many
128
- years before the feature is commonly implemented.
129
121
)
130
122
131
- $(H3 D Programming Language Solutions)
123
+ $(H2 $(LNAME2 d-solutions, D Programming Language Solutions) )
132
124
133
- $(H4 The D Look Ma No Templates Solution)
125
+ $(H3 The D Look Ma No Templates Solution)
134
126
135
127
$(P It is not practical to solve this problem in C++ without
136
128
using templates. In D, one can because D supports typesafe
@@ -155,46 +147,51 @@ void print(...)
155
147
156
148
$(P It isn't elegant or the most efficient,
157
149
but it does work. However it is not the recommended way to write variadic functions.
158
- (It relies on the parameters _argptr and _arguments imported from core.vararg
150
+ (It relies on the parameters ` _argptr` and ` _arguments` imported from ` core.vararg`
159
151
which give a pointer to the values and their types, respectively.)
160
152
)
161
153
162
- $(H4 Translating the Variadic C++ Solution into D)
154
+ $(H3 Translating the Variadic C++ Solution into D)
163
155
164
156
$(P Variadic templates in D enable a straightforward translation
165
- of the proposed C++ variadic syntax :
157
+ of the C++11 variadic solution :
166
158
)
167
159
168
160
---
169
- void print()()
161
+ void print()
170
162
{
171
163
}
172
164
173
165
void print(T, A...)(T t, A a)
174
166
{
167
+ import std.stdio;
175
168
writeln(t);
176
169
print(a);
177
170
}
178
171
---
179
172
180
- $(P There are two function templates . The first provides the
173
+ $(P There are two overloads . The first provides the
181
174
degenerate case of no arguments, and a terminus for the
182
175
recursion of the second. The second has two arguments:
183
- t for the first value and a for the rest of the values.
184
- A... says the parameter is a tuple, and implicit function
185
- template instantiation will fill in A with the list of
186
- all the types following t. So, print(7, 'a', 6.8) will
187
- fill in int for T, and a tuple (char, double) for A.
188
- The parameter a becomes an expression tuple of the arguments.
176
+ `t` for the first value and `a` for any remaining values.
177
+ `A...` says the parameter is a sequence, and
178
+ $(GLOSSARY2 ifti, Implicit Function Template Instantiation)
179
+ will fill in `A` with all the types of any
180
+ arguments supplied following `t`. So, `print(7, 'a', 6.8)` will
181
+ fill in `int` for `T`, and a type sequence `(char, double)` for `A`.
182
+ The parameter `a` is an lvalue sequence of any
183
+ arguments supplied after `t`. See
184
+ $(DDLINK articles/ctarguments, Compile-time Sequences, Compile-time Sequences)
185
+ for more information.
189
186
)
190
187
191
- $(P The function works by printing the first parameter t ,
188
+ $(P The function works by printing the first parameter `t` ,
192
189
and then recursively calling itself with the remaining arguments
193
- a . The recursion terminates when there are no longer any
194
- arguments by calling print()() .
190
+ `a` . The recursion terminates when there are no longer any
191
+ arguments by calling ` print()` .
195
192
)
196
193
197
- $(H4 The Static If Solution)
194
+ $(H3 The Static If Solution)
198
195
199
196
$(P It would be nice to encapsulate all the logic into a
200
197
single function. One way to do that is by using
@@ -213,18 +210,18 @@ void print(A...)(A a)
213
210
}
214
211
---
215
212
216
- $(P Tuples can be manipulated much like arrays.
217
- So a.length resolves to the number of expressions
218
- in the tuple a. a[0] gives the first expression
219
- in the tuple. a[1 .. $] creates a new tuple
220
- by slicing the original tuple .
213
+ $(P Sequences can be manipulated much like arrays.
214
+ So ` a.length` resolves to the number of elements
215
+ in the sequence `a`. ` a[0]` gives the first element
216
+ in the sequence. ` a[1 .. $]` creates a new sequence
217
+ from any remaining elements in the original sequence .
221
218
)
222
219
223
- $(H4 The Foreach Solution)
220
+ $(H3 The Foreach Solution)
224
221
225
- $(P But since tuples can be manipulated like arrays,
226
- we can use a foreach statement to 'loop' over
227
- the tuple 's expressions :
222
+ $(P But since sequences can be manipulated like arrays,
223
+ we can use a ` foreach` statement to iterate over
224
+ the sequence 's elements :
228
225
)
229
226
230
227
---
@@ -254,14 +251,6 @@ $(H3 Acknowledgments)
254
251
255
252
)
256
253
257
- $(H3 References)
258
-
259
- $(OL
260
-
261
- $(LI $(LINK2 http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2006/n2080.pdf, Variadic Templates N2080))
262
-
263
- )
264
-
265
254
)
266
255
267
256
Macros:
0 commit comments