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// Test function types.
17
18#include <experimental/tuple>
19#include <array>
20#include <utility>
21#include <cassert>
22
23// std::array is explicitly allowed to be initialized with A a = { init-list };.
24// Disable the missing braces warning for this reason.
25#include "disable_missing_braces_warning.h"
26
27namespace ex = std::experimental;
28
29int count = 0;
30
31void f_void_0() { ++count; }
32void f_void_1(int i) { count += i; }
33void f_void_2(int x, int y) { count += (x + y); }
34void f_void_3(int x, int y, int z) { count += (x + y + z); }
35
36int f_int_0() { return ++count; }
37int f_int_1(int x) { return count += x; }
38int f_int_2(int x, int y) { return count += (x + y); }
39int f_int_3(int x, int y, int z) { return count += (x + y + z); }
40
41struct A_void_0
42{
43    A_void_0() {}
44    void operator()() { ++count; }
45    void operator()() const { ++count; ++count; }
46};
47
48struct A_void_1
49{
50    A_void_1() {}
51    void operator()(int x) { count += x; }
52    void operator()(int x) const { count += x + 1; }
53};
54
55struct A_void_2
56{
57    A_void_2() {}
58    void operator()(int x, int y) { count += (x + y); }
59    void operator()(int x, int y) const { count += (x + y) + 1; }
60};
61
62struct A_void_3
63{
64    A_void_3() {}
65    void operator()(int x, int y, int z) { count += (x + y + z); }
66    void operator()(int x, int y, int z) const { count += (x + y + z) + 1; }
67};
68
69
70struct A_int_0
71{
72    A_int_0() {}
73    int operator()() { return ++count; }
74    int operator()() const { ++count; return ++count; }
75};
76
77struct A_int_1
78{
79    A_int_1() {}
80    int operator()(int x) { return count += x; }
81    int operator()(int x) const { return count += (x + 1); }
82
83};
84
85struct A_int_2
86{
87    A_int_2() {}
88    int operator()(int x, int y) { return count += (x + y); }
89    int operator()(int x, int y) const { return count += (x + y + 1); }
90};
91
92struct A_int_3
93{
94    A_int_3() {}
95    int operator()(int x, int y, int z) { return count += (x + y + z); }
96    int operator()(int x, int y, int z) const { return count += (x + y + z + 1); }
97};
98
99
100template <class Tuple>
101void test_void_0()
102{
103    count = 0;
104    // function
105    {
106        Tuple t{};
107        ex::apply(f_void_0, t);
108        assert(count == 1);
109    }
110    count = 0;
111    // function pointer
112    {
113        Tuple t{};
114        auto fp = &f_void_0;
115        ex::apply(fp, t);
116        assert(count == 1);
117    }
118    count = 0;
119    // functor
120    {
121        Tuple t{};
122        A_void_0 a;
123        ex::apply(a, t);
124        assert(count == 1);
125    }
126    count = 0;
127    // const functor
128    {
129        Tuple t{};
130        A_void_0 const a;
131        ex::apply(a, t);
132        assert(count == 2);
133    }
134}
135
136template <class Tuple>
137void test_void_1()
138{
139    count = 0;
140    // function
141    {
142        Tuple t{1};
143        ex::apply(f_void_1, t);
144        assert(count == 1);
145    }
146    count = 0;
147    // function pointer
148    {
149        Tuple t{2};
150        void (*fp)(int) = f_void_1;
151        ex::apply(fp, t);
152        assert(count == 2);
153    }
154    count = 0;
155    // functor
156    {
157        Tuple t{3};
158        A_void_1 fn;
159        ex::apply(fn, t);
160        assert(count == 3);
161    }
162    count = 0;
163    // const functor
164    {
165        Tuple t{4};
166        A_void_1 const a;
167        ex::apply(a, t);
168        assert(count == 5);
169    }
170}
171
172template <class Tuple>
173void test_void_2()
174{
175    count = 0;
176    // function
177    {
178        Tuple t{1, 2};
179        ex::apply(f_void_2, t);
180        assert(count == 3);
181    }
182    count = 0;
183    // function pointer
184    {
185        Tuple t{2, 3};
186        auto fp = &f_void_2;
187        ex::apply(fp, t);
188        assert(count == 5);
189    }
190    count = 0;
191    // functor
192    {
193        Tuple t{3, 4};
194        A_void_2 a;
195        ex::apply(a, t);
196        assert(count == 7);
197    }
198    count = 0;
199    // const functor
200    {
201        Tuple t{4, 5};
202        A_void_2 const a;
203        ex::apply(a, t);
204        assert(count == 10);
205    }
206}
207
208template <class Tuple>
209void test_void_3()
210{
211    count = 0;
212    // function
213    {
214        Tuple t{1, 2, 3};
215        ex::apply(f_void_3, t);
216        assert(count == 6);
217    }
218    count = 0;
219    // function pointer
220    {
221        Tuple t{2, 3, 4};
222        auto fp = &f_void_3;
223        ex::apply(fp, t);
224        assert(count == 9);
225    }
226    count = 0;
227    // functor
228    {
229        Tuple t{3, 4, 5};
230        A_void_3 a;
231        ex::apply(a, t);
232        assert(count == 12);
233    }
234    count = 0;
235    // const functor
236    {
237        Tuple t{4, 5, 6};
238        A_void_3 const a;
239        ex::apply(a, t);
240        assert(count == 16);
241    }
242}
243
244
245
246template <class Tuple>
247void test_int_0()
248{
249    count = 0;
250    // function
251    {
252        Tuple t{};
253        assert(1 == ex::apply(f_int_0, t));
254        assert(count == 1);
255    }
256    count = 0;
257    // function pointer
258    {
259        Tuple t{};
260        auto fp = &f_int_0;
261        assert(1 == ex::apply(fp, t));
262        assert(count == 1);
263    }
264    count = 0;
265    // functor
266    {
267        Tuple t{};
268        A_int_0 a;
269        assert(1 == ex::apply(a, t));
270        assert(count == 1);
271    }
272    count = 0;
273    // const functor
274    {
275        Tuple t{};
276        A_int_0 const a;
277        assert(2 == ex::apply(a, t));
278        assert(count == 2);
279    }
280}
281
282template <class Tuple>
283void test_int_1()
284{
285    count = 0;
286    // function
287    {
288        Tuple t{1};
289        assert(1 == ex::apply(f_int_1, t));
290        assert(count == 1);
291    }
292    count = 0;
293    // function pointer
294    {
295        Tuple t{2};
296        int (*fp)(int) = f_int_1;
297        assert(2 == ex::apply(fp, t));
298        assert(count == 2);
299    }
300    count = 0;
301    // functor
302    {
303        Tuple t{3};
304        A_int_1 fn;
305        assert(3 == ex::apply(fn, t));
306        assert(count == 3);
307    }
308    count = 0;
309    // const functor
310    {
311        Tuple t{4};
312        A_int_1 const a;
313        assert(5 == ex::apply(a, t));
314        assert(count == 5);
315    }
316}
317
318template <class Tuple>
319void test_int_2()
320{
321    count = 0;
322    // function
323    {
324        Tuple t{1, 2};
325        assert(3 == ex::apply(f_int_2, t));
326        assert(count == 3);
327    }
328    count = 0;
329    // function pointer
330    {
331        Tuple t{2, 3};
332        auto fp = &f_int_2;
333        assert(5 == ex::apply(fp, t));
334        assert(count == 5);
335    }
336    count = 0;
337    // functor
338    {
339        Tuple t{3, 4};
340        A_int_2 a;
341        assert(7 == ex::apply(a, t));
342        assert(count == 7);
343    }
344    count = 0;
345    // const functor
346    {
347        Tuple t{4, 5};
348        A_int_2 const a;
349        assert(10 == ex::apply(a, t));
350        assert(count == 10);
351    }
352}
353
354template <class Tuple>
355void test_int_3()
356{
357    count = 0;
358    // function
359    {
360        Tuple t{1, 2, 3};
361        assert(6 == ex::apply(f_int_3, t));
362        assert(count == 6);
363    }
364    count = 0;
365    // function pointer
366    {
367        Tuple t{2, 3, 4};
368        auto fp = &f_int_3;
369        assert(9 == ex::apply(fp, t));
370        assert(count == 9);
371    }
372    count = 0;
373    // functor
374    {
375        Tuple t{3, 4, 5};
376        A_int_3 a;
377        assert(12 == ex::apply(a, t));
378        assert(count == 12);
379    }
380    count = 0;
381    // const functor
382    {
383        Tuple t{4, 5, 6};
384        A_int_3 const a;
385        assert(16 == ex::apply(a, t));
386        assert(count == 16);
387    }
388}
389
390template <class Tuple>
391void test_0()
392{
393    test_void_0<Tuple>();
394    test_int_0<Tuple>();
395}
396
397template <class Tuple>
398void test_1()
399{
400    test_void_1<Tuple>();
401    test_int_1<Tuple>();
402}
403
404template <class Tuple>
405void test_2()
406{
407    test_void_2<Tuple>();
408    test_int_2<Tuple>();
409}
410
411template <class Tuple>
412void test_3()
413{
414    test_void_3<Tuple>();
415    test_int_3<Tuple>();
416}
417
418int main()
419{
420    test_0<std::tuple<>>();
421
422    test_1<std::tuple<int>>();
423    test_1<std::array<int, 1>>();
424
425    test_2<std::tuple<int, int>>();
426    test_2<std::pair<int, int>>();
427    test_2<std::array<int, 2>>();
428
429    test_3<std::tuple<int, int, int>>();
430    test_3<std::array<int, 3>>();
431}
432