1 //===----------------------------------------------------------------------===//
2 //
3 // The LLVM Compiler Infrastructure
4 //
5 // This file is dual licensed under the MIT and the University of Illinois Open
6 // Source Licenses. See LICENSE.TXT for details.
7 //
8 //===----------------------------------------------------------------------===//
9
10 // UNSUPPORTED: c++98, c++03, c++11
11
12 // <experimental/tuple>
13
14 // template <class F, class T> constexpr decltype(auto) apply(F &&, T &&)
15
16 // Testing extended function types. The extented function types are those
17 // named by INVOKE but that are not actual callable objects. These include
18 // bullets 1-4 of invoke.
19
20 #include <experimental/tuple>
21 #include <array>
22 #include <utility>
23 #include <cassert>
24
25 int count = 0;
26
27 struct A_int_0
28 {
A_int_0A_int_029 A_int_0() : obj1(0){}
A_int_0A_int_030 A_int_0(int x) : obj1(x) {}
mem1A_int_031 int mem1() { return ++count; }
mem2A_int_032 int mem2() const { return ++count; }
33 int const obj1;
34 };
35
36 struct A_int_1
37 {
A_int_1A_int_138 A_int_1() {}
A_int_1A_int_139 A_int_1(int) {}
mem1A_int_140 int mem1(int x) { return count += x; }
mem2A_int_141 int mem2(int x) const { return count += x; }
42 };
43
44 struct A_int_2
45 {
A_int_2A_int_246 A_int_2() {}
A_int_2A_int_247 A_int_2(int) {}
mem1A_int_248 int mem1(int x, int y) { return count += (x + y); }
mem2A_int_249 int mem2(int x, int y) const { return count += (x + y); }
50 };
51
52 template <class A>
53 struct A_wrap
54 {
A_wrapA_wrap55 A_wrap() {}
A_wrapA_wrap56 A_wrap(int x) : m_a(x) {}
operator *A_wrap57 A & operator*() { return m_a; }
operator *A_wrap58 A const & operator*() const { return m_a; }
59 A m_a;
60 };
61
62 typedef A_wrap<A_int_0> A_wrap_0;
63 typedef A_wrap<A_int_1> A_wrap_1;
64 typedef A_wrap<A_int_2> A_wrap_2;
65
66
67 template <class A>
68 struct A_base : public A
69 {
A_baseA_base70 A_base() : A() {}
A_baseA_base71 A_base(int x) : A(x) {}
72 };
73
74 typedef A_base<A_int_0> A_base_0;
75 typedef A_base<A_int_1> A_base_1;
76 typedef A_base<A_int_2> A_base_2;
77
78 namespace ex = std::experimental;
79
80 template <
81 class Tuple, class ConstTuple
82 , class TuplePtr, class ConstTuplePtr
83 , class TupleWrap, class ConstTupleWrap
84 , class TupleBase, class ConstTupleBase
85 >
test_ext_int_0()86 void test_ext_int_0()
87 {
88 count = 0;
89 typedef A_int_0 T;
90 typedef A_wrap_0 Wrap;
91 typedef A_base_0 Base;
92
93 typedef int(T::*mem1_t)();
94 mem1_t mem1 = &T::mem1;
95
96 typedef int(T::*mem2_t)() const;
97 mem2_t mem2 = &T::mem2;
98
99 typedef int const T::*obj1_t;
100 obj1_t obj1 = &T::obj1;
101
102 // member function w/ref
103 {
104 T a;
105 Tuple t{a};
106 assert(1 == ex::apply(mem1, t));
107 assert(count == 1);
108 }
109 count = 0;
110 // member function w/pointer
111 {
112 T a;
113 TuplePtr t{&a};
114 assert(1 == ex::apply(mem1, t));
115 assert(count == 1);
116 }
117 count = 0;
118 // member function w/base
119 {
120 Base a;
121 TupleBase t{a};
122 assert(1 == ex::apply(mem1, t));
123 assert(count == 1);
124 }
125 count = 0;
126 // member function w/wrap
127 {
128 Wrap a;
129 TupleWrap t{a};
130 assert(1 == ex::apply(mem1, t));
131 assert(count == 1);
132 }
133 count = 0;
134 // const member function w/ref
135 {
136 T const a;
137 ConstTuple t{a};
138 assert(1 == ex::apply(mem2, t));
139 assert(count == 1);
140 }
141 count = 0;
142 // const member function w/pointer
143 {
144 T const a;
145 ConstTuplePtr t{&a};
146 assert(1 == ex::apply(mem2, t));
147 assert(count == 1);
148 }
149 count = 0;
150 // const member function w/base
151 {
152 Base const a;
153 ConstTupleBase t{a};
154 assert(1 == ex::apply(mem2, t));
155 assert(count == 1);
156 }
157 count = 0;
158 // const member function w/wrapper
159 {
160 Wrap const a;
161 ConstTupleWrap t{a};
162 assert(1 == ex::apply(mem2, t));
163 assert(1 == count);
164 }
165 // member object w/ref
166 {
167 T a{42};
168 Tuple t{a};
169 assert(42 == ex::apply(obj1, t));
170 }
171 // member object w/pointer
172 {
173 T a{42};
174 TuplePtr t{&a};
175 assert(42 == ex::apply(obj1, t));
176 }
177 // member object w/base
178 {
179 Base a{42};
180 TupleBase t{a};
181 assert(42 == ex::apply(obj1, t));
182 }
183 // member object w/wrapper
184 {
185 Wrap a{42};
186 TupleWrap t{a};
187 assert(42 == ex::apply(obj1, t));
188 }
189 }
190
191
192 template <
193 class Tuple, class ConstTuple
194 , class TuplePtr, class ConstTuplePtr
195 , class TupleWrap, class ConstTupleWrap
196 , class TupleBase, class ConstTupleBase
197 >
test_ext_int_1()198 void test_ext_int_1()
199 {
200 count = 0;
201 typedef A_int_1 T;
202 typedef A_wrap_1 Wrap;
203 typedef A_base_1 Base;
204
205 typedef int(T::*mem1_t)(int);
206 mem1_t mem1 = &T::mem1;
207
208 typedef int(T::*mem2_t)(int) const;
209 mem2_t mem2 = &T::mem2;
210
211 // member function w/ref
212 {
213 T a;
214 Tuple t{a, 2};
215 assert(2 == ex::apply(mem1, t));
216 assert(count == 2);
217 }
218 count = 0;
219 // member function w/pointer
220 {
221 T a;
222 TuplePtr t{&a, 3};
223 assert(3 == ex::apply(mem1, t));
224 assert(count == 3);
225 }
226 count = 0;
227 // member function w/base
228 {
229 Base a;
230 TupleBase t{a, 4};
231 assert(4 == ex::apply(mem1, t));
232 assert(count == 4);
233 }
234 count = 0;
235 // member function w/wrap
236 {
237 Wrap a;
238 TupleWrap t{a, 5};
239 assert(5 == ex::apply(mem1, t));
240 assert(count == 5);
241 }
242 count = 0;
243 // const member function w/ref
244 {
245 T const a;
246 ConstTuple t{a, 6};
247 assert(6 == ex::apply(mem2, t));
248 assert(count == 6);
249 }
250 count = 0;
251 // const member function w/pointer
252 {
253 T const a;
254 ConstTuplePtr t{&a, 7};
255 assert(7 == ex::apply(mem2, t));
256 assert(count == 7);
257 }
258 count = 0;
259 // const member function w/base
260 {
261 Base const a;
262 ConstTupleBase t{a, 8};
263 assert(8 == ex::apply(mem2, t));
264 assert(count == 8);
265 }
266 count = 0;
267 // const member function w/wrapper
268 {
269 Wrap const a;
270 ConstTupleWrap t{a, 9};
271 assert(9 == ex::apply(mem2, t));
272 assert(9 == count);
273 }
274 }
275
276
277 template <
278 class Tuple, class ConstTuple
279 , class TuplePtr, class ConstTuplePtr
280 , class TupleWrap, class ConstTupleWrap
281 , class TupleBase, class ConstTupleBase
282 >
test_ext_int_2()283 void test_ext_int_2()
284 {
285 count = 0;
286 typedef A_int_2 T;
287 typedef A_wrap_2 Wrap;
288 typedef A_base_2 Base;
289
290 typedef int(T::*mem1_t)(int, int);
291 mem1_t mem1 = &T::mem1;
292
293 typedef int(T::*mem2_t)(int, int) const;
294 mem2_t mem2 = &T::mem2;
295
296 // member function w/ref
297 {
298 T a;
299 Tuple t{a, 1, 1};
300 assert(2 == ex::apply(mem1, t));
301 assert(count == 2);
302 }
303 count = 0;
304 // member function w/pointer
305 {
306 T a;
307 TuplePtr t{&a, 1, 2};
308 assert(3 == ex::apply(mem1, t));
309 assert(count == 3);
310 }
311 count = 0;
312 // member function w/base
313 {
314 Base a;
315 TupleBase t{a, 2, 2};
316 assert(4 == ex::apply(mem1, t));
317 assert(count == 4);
318 }
319 count = 0;
320 // member function w/wrap
321 {
322 Wrap a;
323 TupleWrap t{a, 2, 3};
324 assert(5 == ex::apply(mem1, t));
325 assert(count == 5);
326 }
327 count = 0;
328 // const member function w/ref
329 {
330 T const a;
331 ConstTuple t{a, 3, 3};
332 assert(6 == ex::apply(mem2, t));
333 assert(count == 6);
334 }
335 count = 0;
336 // const member function w/pointer
337 {
338 T const a;
339 ConstTuplePtr t{&a, 3, 4};
340 assert(7 == ex::apply(mem2, t));
341 assert(count == 7);
342 }
343 count = 0;
344 // const member function w/base
345 {
346 Base const a;
347 ConstTupleBase t{a, 4, 4};
348 assert(8 == ex::apply(mem2, t));
349 assert(count == 8);
350 }
351 count = 0;
352 // const member function w/wrapper
353 {
354 Wrap const a;
355 ConstTupleWrap t{a, 4, 5};
356 assert(9 == ex::apply(mem2, t));
357 assert(9 == count);
358 }
359 }
360
main()361 int main()
362 {
363 {
364 test_ext_int_0<
365 std::tuple<A_int_0 &>, std::tuple<A_int_0 const &>
366 , std::tuple<A_int_0 *>, std::tuple<A_int_0 const *>
367 , std::tuple<A_wrap_0 &>, std::tuple<A_wrap_0 const &>
368 , std::tuple<A_base_0 &>, std::tuple<A_base_0 const &>
369 >();
370 test_ext_int_0<
371 std::tuple<A_int_0>, std::tuple<A_int_0 const>
372 , std::tuple<A_int_0 *>, std::tuple<A_int_0 const *>
373 , std::tuple<A_wrap_0>, std::tuple<A_wrap_0 const>
374 , std::tuple<A_base_0>, std::tuple<A_base_0 const>
375 >();
376 test_ext_int_0<
377 std::array<A_int_0, 1>, std::array<A_int_0 const, 1>
378 , std::array<A_int_0*, 1>, std::array<A_int_0 const*, 1>
379 , std::array<A_wrap_0, 1>, std::array<A_wrap_0 const, 1>
380 , std::array<A_base_0, 1>, std::array<A_base_0 const, 1>
381 >();
382 }
383 {
384 test_ext_int_1<
385 std::tuple<A_int_1 &, int>, std::tuple<A_int_1 const &, int>
386 , std::tuple<A_int_1 *, int>, std::tuple<A_int_1 const *, int>
387 , std::tuple<A_wrap_1 &, int>, std::tuple<A_wrap_1 const &, int>
388 , std::tuple<A_base_1 &, int>, std::tuple<A_base_1 const &, int>
389 >();
390 test_ext_int_1<
391 std::tuple<A_int_1, int>, std::tuple<A_int_1 const, int>
392 , std::tuple<A_int_1 *, int>, std::tuple<A_int_1 const *, int>
393 , std::tuple<A_wrap_1, int>, std::tuple<A_wrap_1 const, int>
394 , std::tuple<A_base_1, int>, std::tuple<A_base_1 const, int>
395 >();
396 test_ext_int_1<
397 std::pair<A_int_1 &, int>, std::pair<A_int_1 const &, int>
398 , std::pair<A_int_1 *, int>, std::pair<A_int_1 const *, int>
399 , std::pair<A_wrap_1 &, int>, std::pair<A_wrap_1 const &, int>
400 , std::pair<A_base_1 &, int>, std::pair<A_base_1 const &, int>
401 >();
402 test_ext_int_1<
403 std::pair<A_int_1, int>, std::pair<A_int_1 const, int>
404 , std::pair<A_int_1 *, int>, std::pair<A_int_1 const *, int>
405 , std::pair<A_wrap_1, int>, std::pair<A_wrap_1 const, int>
406 , std::pair<A_base_1, int>, std::pair<A_base_1 const, int>
407 >();
408 }
409 {
410 test_ext_int_2<
411 std::tuple<A_int_2 &, int, int>, std::tuple<A_int_2 const &, int, int>
412 , std::tuple<A_int_2 *, int, int>, std::tuple<A_int_2 const *, int, int>
413 , std::tuple<A_wrap_2 &, int, int>, std::tuple<A_wrap_2 const &, int, int>
414 , std::tuple<A_base_2 &, int, int>, std::tuple<A_base_2 const &, int, int>
415 >();
416 test_ext_int_2<
417 std::tuple<A_int_2, int, int>, std::tuple<A_int_2 const, int, int>
418 , std::tuple<A_int_2 *, int, int>, std::tuple<A_int_2 const *, int, int>
419 , std::tuple<A_wrap_2, int, int>, std::tuple<A_wrap_2 const, int, int>
420 , std::tuple<A_base_2, int, int>, std::tuple<A_base_2 const, int, int>
421 >();
422 }
423 }
424