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