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 with different ref/ptr/cv qualified argument types.
17 
18 #include <experimental/tuple>
19 #include <array>
20 #include <utility>
21 #include <cassert>
22 
23 namespace ex = std::experimental;
24 
call_with_value(int x,int y)25 int call_with_value(int x, int y) { return (x + y); }
call_with_ref(int & x,int & y)26 int call_with_ref(int & x, int & y) { return (x + y); }
call_with_const_ref(int const & x,int const & y)27 int call_with_const_ref(int const & x, int const & y) { return (x + y); }
call_with_rvalue_ref(int && x,int && y)28 int call_with_rvalue_ref(int && x, int && y) { return (x + y); }
call_with_pointer(int * x,int * y)29 int call_with_pointer(int * x, int * y) { return (*x + *y); }
call_with_const_pointer(int const * x,int const * y)30 int call_with_const_pointer(int const* x, int const * y) { return (*x + *y); }
31 
32 
33 template <class Tuple>
test_values()34 void test_values()
35 {
36     {
37         Tuple t{1, 2};
38         assert(3 == ex::apply(call_with_value, t));
39     }
40     {
41         Tuple t{2, 2};
42         assert(4 == ex::apply(call_with_ref, t));
43     }
44     {
45         Tuple t{2, 3};
46         assert(5 == ex::apply(call_with_const_ref, t));
47     }
48     {
49         Tuple t{3, 3};
50         assert(6 == ex::apply(call_with_rvalue_ref, static_cast<Tuple &&>(t)));
51     }
52     {
53         Tuple const t{4, 4};
54         assert(8 == ex::apply(call_with_value, t));
55     }
56     {
57         Tuple const t{4, 5};
58         assert(9 == ex::apply(call_with_const_ref, t));
59     }
60 }
61 
62 template <class Tuple>
test_refs()63 void test_refs()
64 {
65     int x = 0;
66     int y = 0;
67     {
68         x = 1; y = 2;
69         Tuple t{x, y};
70         assert(3 == ex::apply(call_with_value, t));
71     }
72     {
73         x = 2; y = 2;
74         Tuple t{x, y};
75         assert(4 == ex::apply(call_with_ref, t));
76     }
77     {
78         x = 2; y = 3;
79         Tuple t{x, y};
80         assert(5 == ex::apply(call_with_const_ref, t));
81     }
82     {
83         x = 3; y = 3;
84         Tuple const t{x, y};
85         assert(6 == ex::apply(call_with_value, t));
86     }
87     {
88         x = 3; y = 4;
89         Tuple const t{x, y};
90         assert(7 == ex::apply(call_with_const_ref, t));
91     }
92 }
93 
94 template <class Tuple>
test_const_refs()95 void test_const_refs()
96 {
97     int x = 0;
98     int y = 0;
99     {
100         x = 1; y = 2;
101         Tuple t{x, y};
102         assert(3 == ex::apply(call_with_value, t));
103     }
104     {
105         x = 2; y = 3;
106         Tuple t{x, y};
107         assert(5 == ex::apply(call_with_const_ref, t));
108     }
109     {
110         x = 3; y = 3;
111         Tuple const t{x, y};
112         assert(6 == ex::apply(call_with_value, t));
113     }
114     {
115         x = 3; y = 4;
116         Tuple const t{x, y};
117         assert(7 == ex::apply(call_with_const_ref, t));
118     }
119 }
120 
121 
122 template <class Tuple>
test_pointer()123 void test_pointer()
124 {
125     int x = 0;
126     int y = 0;
127     {
128         x = 2; y = 2;
129         Tuple t{&x, &y};
130         assert(4 == ex::apply(call_with_pointer, t));
131     }
132     {
133         x = 2; y = 3;
134         Tuple t{&x, &y};
135         assert(5 == ex::apply(call_with_const_pointer, t));
136     }
137     {
138         x = 3; y = 4;
139         Tuple const t{&x, &y};
140         assert(7 == ex::apply(call_with_const_pointer, t));
141     }
142 }
143 
144 
145 template <class Tuple>
test_const_pointer()146 void test_const_pointer()
147 {
148     int x = 0;
149     int y = 0;
150     {
151         x = 2; y = 3;
152         Tuple t{&x, &y};
153         assert(5 == ex::apply(call_with_const_pointer, t));
154     }
155     {
156         x = 3; y = 4;
157         Tuple const t{&x, &y};
158         assert(7 == ex::apply(call_with_const_pointer, t));
159     }
160 }
161 
162 
main()163 int main()
164 {
165     test_values<std::tuple<int, int>>();
166     test_values<std::pair<int, int>>();
167     test_values<std::array<int, 2>>();
168 
169     test_refs<std::tuple<int &, int &>>();
170     test_refs<std::pair<int &, int &>>();
171 
172     test_const_refs<std::tuple<int const &, int const &>>();
173     test_const_refs<std::pair<int const &, int const &>>();
174 
175     test_pointer<std::tuple<int *, int *>>();
176     test_pointer<std::pair<int *, int *>>();
177     test_pointer<std::array<int *, 2>>();
178 
179     test_const_pointer<std::tuple<int const *, int const *>>();
180     test_const_pointer<std::pair<int const *, int const *>>();
181     test_const_pointer<std::array<int const *, 2>>();
182 }
183