Imported Upstream version 2.99.2
[platform/upstream/libsigc++.git] / tests / test_tuple_for_each.cc
1 /* Copyright (C) 2016 Murray Cumming
2  *
3  * This program is free software: you can redistribute it and/or modify
4  * it under the terms of the GNU General Public License as published by
5  * the Free Software Foundation, either version 3 of the License, or
6  *  (at your option) any later version.
7  *
8  * This program is distributed in the hope that it will be useful,
9  * but WITHOUT ANY WARRANTY; without even the implied warranty of
10  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
11  * GNU General Public License for more details.
12  *
13  * You should have received a copy of the GNU General Public License
14  * along with this program.  If not, see <http://www.gnu.org/licenses/
15  */
16
17 #include <cassert>
18 #include <cstdlib>
19 #include <sigc++/tuple-utils/tuple_for_each.h>
20 #include <utility>
21 //#include <typeinfo>
22 #include <iostream>
23 #include <functional>
24
25 template <class T_element_from>
26 class for_each_simple {
27 public:
28   static void
29   visit(const T_element_from& from) {
30     std::cout << "for_each_simple(): " << std::to_string(from) << std::endl;
31   }
32 };
33
34 void
35 test_tuple_for_each_same_types() {
36   {
37     auto t_original = std::make_tuple(1, 2, 3);
38     sigc::internal::tuple_for_each<for_each_simple>(t_original);
39   }
40
41   {
42     auto t_original = std::make_tuple(1, (double)2.1f, 3);
43     sigc::internal::tuple_for_each<for_each_simple>(t_original);
44   }
45 }
46
47 template <class T_element_from>
48 class for_each_simple_with_extras {
49 public:
50   static void
51   visit(const T_element_from& from, int extra1, const std::string& extra2) {
52     std::cout << "for_each_simple_with_extras(): from=" << std::to_string(from)
53               << ", extra1: " << extra1 << ", extra2: " << extra2 << std::endl;
54   }
55 };
56
57 void
58 test_tuple_for_each_same_types_with_extras() {
59   {
60     auto t_original = std::make_tuple(1, (double)2.1f, 3);
61     sigc::internal::tuple_for_each<for_each_simple_with_extras>(
62       t_original, 89, "eightynine");
63   }
64 }
65
66 template <class T_element_from>
67 class for_each_simple_with_nonconst_extras {
68 public:
69   static void
70   visit(const T_element_from& from, int& extra) {
71     extra += (int)from;
72   }
73 };
74
75 void
76 test_tuple_for_each_same_types_with_nonconst_extras() {
77   {
78     auto t_original = std::make_tuple(1, (double)2.1f, 3);
79     int extra = 0;
80
81     sigc::internal::tuple_for_each<for_each_simple_with_nonconst_extras>(t_original, extra);
82     // std::cout << "extra: " << extra << std::endl;
83     assert(extra == 6);
84   }
85 }
86
87 // The general template declaration.
88 // We then provide specializations for each type,
89 // so we can test having a different return value for each T_element_from type.
90 template <class T_element_from>
91 class visitor_with_specializations;
92
93 // An int will be converted to a std::string:
94 template <>
95 class visitor_with_specializations<int> {
96 public:
97   static void
98   visit(const int& from) {
99     std::cout << "visitor_with_specializations::visit(): "
100               << std::to_string(from) << std::endl;
101   }
102 };
103
104 // A double will be converted to a char:
105 template <>
106 class visitor_with_specializations<double> {
107 public:
108   static void
109   visit(const double& from) {
110     std::cout << "visitor_with_specializations::visit(): "
111               << std::to_string(from)[0] << std::endl;
112   }
113 };
114
115 // A std::string will be converted to an int:
116 template <>
117 class visitor_with_specializations<std::string> {
118 public:
119   static void
120   visit(const std::string& from) {
121     std::cout << "visitor_with_specializations::visit(): " << std::stoi(from)
122               << std::endl;
123   }
124 };
125
126 // A const char* will be converted to an int:
127 template <>
128 class visitor_with_specializations<const char*> {
129 public:
130   static void
131   visit(const char* from) {
132     std::cout << "visitor_with_specializations::visit(): " << std::stoi(from)
133               << std::endl;
134   }
135 };
136
137 void
138 test_tuple_for_each_multiple_types() {
139   auto t_original = std::make_tuple(1, (double)2.1f, std::string("3"));
140   sigc::internal::tuple_for_each<visitor_with_specializations>(t_original);
141 }
142
143 template <class T_element_from>
144 class for_each_nonconst {
145 public:
146   static void
147   visit(T_element_from& from) {
148     from *= 2;
149     // Or, for instance, call a non-const method on from.
150   }
151 };
152
153 void
154 test_tuple_for_each_nonconst() {
155   auto t = std::make_tuple(1, 2, 3);
156   sigc::internal::tuple_for_each<for_each_nonconst, decltype(t)&>(t);
157   std::cout << std::get<0>(t) << std::endl;
158   assert(std::get<0>(t) == 2);
159   assert(std::get<1>(t) == 4);
160   assert(std::get<2>(t) == 6);
161 }
162
163 void
164 test_tuple_for_each_stdref() {
165   {
166     int a = 1;
167     int b = 2;
168     int c = 3;
169     auto t_original = std::make_tuple(std::ref(a), std::ref(b), std::ref(c));
170     sigc::internal::tuple_for_each<for_each_simple>(t_original);
171   }
172
173   {
174     int a = 1;
175     int b = 2;
176     int c = 3;
177     auto t_original = std::make_tuple(std::ref(a), std::ref(b), std::ref(c));
178     sigc::internal::tuple_for_each<for_each_nonconst>(t_original);
179     assert(a == 2);
180     assert(b == 4);
181     assert(c == 6);
182   }
183 }
184
185 static std::string correct_sequence_output;
186
187 template <class T_element_from>
188 class for_each_correct_sequence {
189 public:
190   static void
191   visit(const T_element_from& from) {
192     //std::cout << "from: " << from << std::endl;
193     correct_sequence_output += std::to_string(from);
194   }
195 };
196
197 void
198 test_tuple_for_each_correct_sequence() {
199   correct_sequence_output.clear();
200   auto t = std::make_tuple(1, 2, 3);
201   sigc::internal::tuple_for_each<for_each_correct_sequence>(t);
202   //std::cout << "correct_sequence_output: " << correct_sequence_output << std::endl;
203   assert(correct_sequence_output == "123");
204 }
205
206 void
207 test_tuple_for_each_empty_tuple() {
208   auto t = std::tuple<>();
209   sigc::internal::tuple_for_each<for_each_simple>(t);
210 }
211
212 constexpr
213 void
214 test_tuple_for_each_constexpr() {
215   constexpr auto t_original = std::make_tuple(1, (double)2.1f, "3");
216   sigc::internal::tuple_for_each<visitor_with_specializations>(t_original);
217 }
218
219 int
220 main() {
221   test_tuple_for_each_same_types();
222   test_tuple_for_each_same_types_with_extras();
223   test_tuple_for_each_same_types_with_nonconst_extras();
224
225   test_tuple_for_each_multiple_types();
226
227   test_tuple_for_each_nonconst();
228   
229   test_tuple_for_each_stdref();
230
231   test_tuple_for_each_correct_sequence();
232
233   test_tuple_for_each_empty_tuple();
234
235   test_tuple_for_each_constexpr();
236
237   return EXIT_SUCCESS;
238 }