blob: 322554925d3ff61194a4db06ffd732f76e60e667 [file] [log] [blame]
Eric Fiselier13858ee2015-03-17 18:28:14 +00001//===----------------------------------------------------------------------===//
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
Eric Fiselier13858ee2015-03-17 18:28:14 +000025int count = 0;
26
27struct A_int_0
28{
29 A_int_0() : obj1(0){}
30 A_int_0(int x) : obj1(x) {}
31 int mem1() { return ++count; }
32 int mem2() const { return ++count; }
33 int const obj1;
34};
35
36struct A_int_1
37{
38 A_int_1() {}
39 A_int_1(int) {}
40 int mem1(int x) { return count += x; }
41 int mem2(int x) const { return count += x; }
42};
43
44struct A_int_2
45{
46 A_int_2() {}
47 A_int_2(int) {}
48 int mem1(int x, int y) { return count += (x + y); }
49 int mem2(int x, int y) const { return count += (x + y); }
50};
51
52template <class A>
53struct A_wrap
54{
55 A_wrap() {}
56 A_wrap(int x) : m_a(x) {}
57 A & operator*() { return m_a; }
58 A const & operator*() const { return m_a; }
59 A m_a;
60};
61
62typedef A_wrap<A_int_0> A_wrap_0;
63typedef A_wrap<A_int_1> A_wrap_1;
64typedef A_wrap<A_int_2> A_wrap_2;
65
66
67template <class A>
68struct A_base : public A
69{
70 A_base() : A() {}
71 A_base(int x) : A(x) {}
72};
73
74typedef A_base<A_int_0> A_base_0;
75typedef A_base<A_int_1> A_base_1;
76typedef A_base<A_int_2> A_base_2;
77
78namespace ex = std::experimental;
79
80template <
81 class Tuple, class ConstTuple
82 , class TuplePtr, class ConstTuplePtr
83 , class TupleWrap, class ConstTupleWrap
84 , class TupleBase, class ConstTupleBase
85 >
86void 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
192template <
193 class Tuple, class ConstTuple
194 , class TuplePtr, class ConstTuplePtr
195 , class TupleWrap, class ConstTupleWrap
196 , class TupleBase, class ConstTupleBase
197 >
198void 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
277template <
278 class Tuple, class ConstTuple
279 , class TuplePtr, class ConstTuplePtr
280 , class TupleWrap, class ConstTupleWrap
281 , class TupleBase, class ConstTupleBase
282 >
283void 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
361int 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}