Ticket #2749: main.cpp

File main.cpp, 17.8 KB (added by nowake@…, 14 years ago)

sample code

Line 
1#include <iostream>
2#include <conio.h>
3#include <string>
4#include <boost/timer.hpp>
5#include <boost/any.hpp>
6#include <boost/noncopyable.hpp>
7#include <boost/tuple/tuple.hpp>
8#include <boost/lexical_cast.hpp>
9
10#include "Multimethod.hpp"
11#include "Holder.hpp"
12
13struct Timer {
14 ~Timer() {
15 std::cout << "Test time: " << timer_.elapsed() << " sec." << std::endl;
16 std::cout << "Press any key" << std::endl;
17 getchar();
18 };
19 boost::timer timer_;
20} timer;
21
22#define BOOST_TEST_MODULE Test
23#define BOOST_TEST_MAIN
24#include <boost/test/included/unit_test.hpp>
25
26using namespace std;
27using namespace boost;
28using namespace unit_test;
29using namespace unit_test_framework;
30
31
32BOOST_AUTO_TEST_SUITE(TestHolder)
33
34
35// Multi method Sample
36
37namespace TestMultimethod {
38 struct A {};
39 struct B {};
40 struct C { C() : n() {}; unsigned int n; };
41 struct D { D() : n() {}; unsigned int n; };
42 struct TestAnyMethod0 { // Multi method
43 string operator()(any& arg1) { return Multimethod::apply<string>(*this, arg1); };
44 string operator()(any& arg1, any& arg2) { return Multimethod::apply<string>(*this, arg1, arg2); };
45 string operator()() const { return string("No argument"); };
46 string operator()(int value) const { return string("int"); };
47 string operator()(double value) const { return string("double"); };
48 string operator()(A value) const { return string("struct A"); };
49 string operator()(B& value) const { return string("struct B"); };
50 string operator()(const B& value) const { return string("struct B"); };
51 string operator()(C value) const { return lexical_cast<string>(value.n++); };
52 string operator()(D& value) const { return lexical_cast<string>(value.n++); };
53 string operator()(const D& value) const { return lexical_cast<string>(value.n); };
54 string operator()(int value1, int value2) const { return string("int, int"); };
55 string operator()(int value1, double value2) const { return string("int, double"); };
56 string operator()(double value1, double value2) const { return string("double, double"); };
57 };
58 // "entry" Multi methods
59 bool m01(Multimethod::entry<string, any, TestAnyMethod0, int>());
60 bool m02(Multimethod::entry<string, any, TestAnyMethod0, const int>());
61 bool m03(Multimethod::entry<string, any, TestAnyMethod0, double>());
62 bool m04(Multimethod::entry<string, any, TestAnyMethod0, A>());
63 bool m05(Multimethod::entry<string, any, TestAnyMethod0, B>());
64 bool m06(Multimethod::entry<string, any, TestAnyMethod0, C>());
65 bool m07(Multimethod::entry<string, any, TestAnyMethod0, D>());
66 bool m08(Multimethod::entry<string, any, TestAnyMethod0, int, int>());
67 bool m09(Multimethod::entry<string, any, TestAnyMethod0, int, double>());
68 bool m0a(Multimethod::entry<string, any, TestAnyMethod0, double, double>());
69 bool a00(Multimethod::entry<any, any, TestAnyMethod0>());
70 bool a01(Multimethod::entry<any, any, TestAnyMethod0, int>());
71 bool a02(Multimethod::entry<any, any, TestAnyMethod0, const int>());
72 bool a03(Multimethod::entry<any, any, TestAnyMethod0, double>());
73 bool a04(Multimethod::entry<any, any, TestAnyMethod0, A>());
74 bool a05(Multimethod::entry<any, any, TestAnyMethod0, B>());
75 bool a06(Multimethod::entry<any, any, TestAnyMethod0, C>());
76 bool a07(Multimethod::entry<any, any, TestAnyMethod0, D>());
77 bool a08(Multimethod::entry<any, any, TestAnyMethod0, int, int>());
78 bool a09(Multimethod::entry<any, any, TestAnyMethod0, int, double>());
79 bool a0a(Multimethod::entry<any, any, TestAnyMethod0, double, double>());
80
81
82 BOOST_AUTO_TEST_CASE(test01)
83 {
84 TestAnyMethod0 m;
85 any a(0);
86 BOOST_CHECK_EQUAL(m(a), "int");
87 a = 0.0;
88 BOOST_CHECK_EQUAL(m(a), "double");
89 a = A();
90 BOOST_CHECK_EQUAL(m(a), "struct A");
91 a = B();
92 BOOST_CHECK_EQUAL(m(a), "struct B");
93 any b(0);
94 a = 0;
95 BOOST_CHECK_EQUAL(m(a, b), "int, int");
96 b = 0.0;
97 BOOST_CHECK_EQUAL(m(a, b), "int, double");
98 a = 0.0;
99 BOOST_CHECK_EQUAL(m(a, b), "double, double");
100 a = C();
101 BOOST_CHECK_EQUAL(m(a), "0");
102 BOOST_CHECK_EQUAL(m(a), "0");
103 BOOST_CHECK_EQUAL(m(a), "0");
104 BOOST_CHECK_EQUAL(m(a), "0");
105 a = D();
106 BOOST_CHECK_EQUAL(m(a), "0");
107 BOOST_CHECK_EQUAL(m(a), "1");
108 BOOST_CHECK_EQUAL(m(a), "2");
109 BOOST_CHECK_EQUAL(m(a), "3");
110 }
111
112 BOOST_AUTO_TEST_CASE(test02)
113 {
114 // You can use boost::any to hold multi method.
115 // but you must use Multimethod::apply in this case.
116 TestAnyMethod0 m0;
117 any m(m0);
118 BOOST_CHECK_EQUAL(any_cast<string>(Multimethod::apply<any>(m)), "No argument");
119 any a(0);
120 BOOST_CHECK_EQUAL(any_cast<string>(Multimethod::apply<any>(m, a)), "int");
121 a = 0.0;
122 BOOST_CHECK_EQUAL(any_cast<string>(Multimethod::apply<any>(m, a)), "double");
123 a = A();
124 BOOST_CHECK_EQUAL(any_cast<string>(Multimethod::apply<any>(m, a)), "struct A");
125 a = B();
126 BOOST_CHECK_EQUAL(any_cast<string>(Multimethod::apply<any>(m, a)), "struct B");
127 any b(0);
128 a = 0;
129 BOOST_CHECK_EQUAL(any_cast<string>(Multimethod::apply<any>(m, a, b)), "int, int");
130 b = 0.0;
131 BOOST_CHECK_EQUAL(any_cast<string>(Multimethod::apply<any>(m, a, b)), "int, double");
132 a = 0.0;
133 BOOST_CHECK_EQUAL(any_cast<string>(Multimethod::apply<any>(m, a, b)), "double, double");
134 a = C();
135 BOOST_CHECK_EQUAL(any_cast<string>(Multimethod::apply<any>(m, a)), "0");
136 BOOST_CHECK_EQUAL(any_cast<string>(Multimethod::apply<any>(m, a)), "0");
137 BOOST_CHECK_EQUAL(any_cast<string>(Multimethod::apply<any>(m, a)), "0");
138 BOOST_CHECK_EQUAL(any_cast<string>(Multimethod::apply<any>(m, a)), "0");
139 a = D();
140 BOOST_CHECK_EQUAL(any_cast<string>(Multimethod::apply<any>(m, a)), "0");
141 BOOST_CHECK_EQUAL(any_cast<string>(Multimethod::apply<any>(m, a)), "1");
142 BOOST_CHECK_EQUAL(any_cast<string>(Multimethod::apply<any>(m, a)), "2");
143 BOOST_CHECK_EQUAL(any_cast<string>(Multimethod::apply<any>(m, a)), "3");
144 }
145
146 BOOST_AUTO_TEST_CASE(test03)
147 {
148 // You can also use not any classes to call multi methods.
149 TestAnyMethod0 m0;
150 any m(m0);
151 any a(0);
152 BOOST_CHECK_EQUAL(any_cast<string>(Multimethod::apply<any>(m, a)), "int");
153 BOOST_CHECK_EQUAL(any_cast<string>(Multimethod::apply<any>(m, 1)), "int");
154 }
155
156
157 struct TestAnyMethod1 {
158 string operator()(any& arg1) { return Multimethod::apply<string>(*this, arg1); };
159 string operator()(any& arg1, any& arg2) { return Multimethod::apply<string>(*this, arg1, arg2); };
160 string operator()(int value) const { return string("1: int"); };
161 string operator()(double value) const { return string("1: double"); };
162 string operator()(A value) const { return string("1: struct A"); };
163 string operator()(B& value) const { return string("1: struct B"); };
164 string operator()(const B& value) const { return string("1: struct B"); };
165 string operator()(C value) const { return string("1: ") + lexical_cast<string>(value.n++); };
166 string operator()(D& value) const { return string("1: ") + lexical_cast<string>(value.n++); };
167 string operator()(const D& value) const { return string("1: ") + lexical_cast<string>(value.n); };
168 string operator()(int value1, int value2) const { return string("1: int, int"); };
169 string operator()(int value1, double value2) const { return string("1: int, double"); };
170 string operator()(double value1, double value2) const { return string("1: double, double"); };
171 };
172 bool a10(Multimethod::entry<any, any, TestAnyMethod1, int>());
173 bool a11(Multimethod::entry<any, any, TestAnyMethod1, double>());
174 bool a12(Multimethod::entry<any, any, TestAnyMethod1, A>());
175 bool a13(Multimethod::entry<any, any, TestAnyMethod1, B>());
176 bool a14(Multimethod::entry<any, any, TestAnyMethod1, C>());
177 bool a15(Multimethod::entry<any, any, TestAnyMethod1, D>());
178 bool a16(Multimethod::entry<any, any, TestAnyMethod1, int, int>());
179 bool a17(Multimethod::entry<any, any, TestAnyMethod1, int, double>());
180 bool a18(Multimethod::entry<any, any, TestAnyMethod1, double, double>());
181
182
183 BOOST_AUTO_TEST_CASE(test04)
184 {
185 // Return boost::any.
186 TestAnyMethod1 m1;
187 any m(m1);
188 any a(0);
189 BOOST_CHECK_EQUAL(any_cast<string>(Multimethod::apply<any>(m, a)), "1: int");
190 a = 0.0;
191 BOOST_CHECK_EQUAL(any_cast<string>(Multimethod::apply<any>(m, a)), "1: double");
192 a = A();
193 BOOST_CHECK_EQUAL(any_cast<string>(Multimethod::apply<any>(m, a)), "1: struct A");
194 a = B();
195 BOOST_CHECK_EQUAL(any_cast<string>(Multimethod::apply<any>(m, a)), "1: struct B");
196 any b(0);
197 a = 0;
198 BOOST_CHECK_EQUAL(any_cast<string>(Multimethod::apply<any>(m, a, b)), "1: int, int");
199 b = 0.0;
200 BOOST_CHECK_EQUAL(any_cast<string>(Multimethod::apply<any>(m, a, b)), "1: int, double");
201 a = 0.0;
202 BOOST_CHECK_EQUAL(any_cast<string>(Multimethod::apply<any>(m, a, b)), "1: double, double");
203 a = C();
204 BOOST_CHECK_EQUAL(any_cast<string>(Multimethod::apply<any>(m, a)), "1: 0");
205 BOOST_CHECK_EQUAL(any_cast<string>(Multimethod::apply<any>(m, a)), "1: 0");
206 BOOST_CHECK_EQUAL(any_cast<string>(Multimethod::apply<any>(m, a)), "1: 0");
207 BOOST_CHECK_EQUAL(any_cast<string>(Multimethod::apply<any>(m, a)), "1: 0");
208 a = D();
209 BOOST_CHECK_EQUAL(any_cast<string>(Multimethod::apply<any>(m, a)), "1: 0");
210 BOOST_CHECK_EQUAL(any_cast<string>(Multimethod::apply<any>(m, a)), "1: 1");
211 BOOST_CHECK_EQUAL(any_cast<string>(Multimethod::apply<any>(m, a)), "1: 2");
212 BOOST_CHECK_EQUAL(any_cast<string>(Multimethod::apply<any>(m, a)), "1: 3");
213 };
214}
215
216
217// Holder Sample
218
219namespace TestHolder {
220 struct TestMethod0 {
221 string operator()(Holder& arg1) { return Multimethod::apply<string>(*this, arg1); };
222 string operator()(Holder& arg1, Holder& arg2) { return Multimethod::apply<string>(*this, arg1, arg2); };
223 string operator()() const { return string("No argument"); };
224 string operator()(int value) const { return string("int0"); };
225 string operator()(double value) const { return string("double0"); };
226 string operator()(int arg1, int arg2) const { return string("int0, int0"); };
227 string operator()(int arg1, int arg2, int arg3) const { return string("string(int, int, int)"); };
228 };
229
230 // Entry for multi method
231 bool tm00(Multimethod::entry<string, Holder, TestMethod0>());
232 bool tm01(Multimethod::entry<string, Holder, TestMethod0, int>());
233 bool tm02(Multimethod::entry<string, Holder, TestMethod0, double>());
234 bool tm03(Multimethod::entry<string, Holder, TestMethod0, char>());
235 bool tm04(Multimethod::entry<string, Holder, TestMethod0, int, int>());
236
237 // Entry for Holder's operator()
238 bool htm00(Holder::entry<TestMethod0>());
239 bool htm01(Holder::entry<TestMethod0, int>());
240 bool htm02(Holder::entry<TestMethod0, double>());
241 bool htm03(Holder::entry<TestMethod0, char>());
242 bool htm04(Holder::entry<TestMethod0, int, int>());
243 bool htm05(Holder::entry<TestMethod0, int, int, int>());
244
245
246 BOOST_AUTO_TEST_CASE(test01)
247 {
248 // Multi method calling.
249 TestMethod0 m;
250 Holder h0(0);
251 BOOST_CHECK_EQUAL(m(h0), "int0");
252 Holder h1(0.0);
253 BOOST_CHECK_EQUAL(m(h1), "double0");
254 h1 = 0;
255 BOOST_CHECK_EQUAL(m(h1), "int0");
256 BOOST_CHECK_EQUAL(m(h1, h1), "int0, int0");
257 h1 = 'a';
258 BOOST_CHECK_EQUAL(m(h1), "int0");
259 }
260
261
262 struct TestMethod1 {
263 string operator()(Holder& value) { return Multimethod::apply<string>(*this, value); };
264 string operator()() const { return string("No argument"); };
265 string operator()(int value) const { return string("int1"); };
266 string operator()(double value) const { return string("double1"); };
267 };
268
269 // Entry for multi method
270 bool tm10(Multimethod::entry<string, Holder, TestMethod1>());
271 bool tm11(Multimethod::entry<string, Holder, TestMethod1, int>());
272 bool tm12(Multimethod::entry<string, Holder, TestMethod1, double>());
273 bool tm13(Multimethod::entry<string, Holder, TestMethod1, char>());
274
275 // Entry for Holder's operator()
276 bool htm10(Holder::entry<TestMethod1>());
277 bool htm11(Holder::entry<TestMethod1, int>());
278 bool htm12(Holder::entry<TestMethod1, double>());
279 bool htm13(Holder::entry<TestMethod1, char>());
280
281
282 BOOST_AUTO_TEST_CASE(test02)
283 {
284 TestMethod1 m;
285 Holder h0(0);
286 BOOST_CHECK_EQUAL(m(h0), "int1");
287 Holder h1(0.0);
288 BOOST_CHECK_EQUAL(m(h1), "double1");
289 h1 = 0;
290 BOOST_CHECK_EQUAL(m(h1), "int1");
291 h1 = 'a';
292 BOOST_CHECK_EQUAL(m(h1), "int1");
293 }
294
295 struct TestVoidMethod {
296 void operator()(Holder& value) { Multimethod::apply<void>(*this, value); };
297 void operator()(int value) const { string("int"); };
298 void operator()(double value) const { string("double"); };
299 };
300 bool tvm1(Multimethod::entry<void, Holder, TestVoidMethod, int>());
301 bool tvm2(Multimethod::entry<void, Holder, TestVoidMethod, double>());
302 bool tvm3(Multimethod::entry<void, Holder, TestVoidMethod, char>());
303
304 bool htvm1(Holder::entry<TestVoidMethod, int>());
305 bool htvm2(Holder::entry<TestVoidMethod, double>());
306 bool htvm3(Holder::entry<TestVoidMethod, char>());
307
308
309 BOOST_AUTO_TEST_CASE(test03)
310 {
311 // void method calling.
312 TestVoidMethod m;
313 Holder h0(0);
314 m(h0);
315 }
316
317
318 struct AA { AA() : val_() {}; unsigned int val_; };
319 struct BB { BB() : val_() {}; unsigned int val_; };
320 struct TestMethod2 {
321 unsigned int operator()(Holder& value) { return Multimethod::apply<unsigned int>(*this, value); };
322 unsigned int operator()(AA& value) const { return value.val_++; };
323 unsigned int operator()(const AA& value) const { return value.val_; };
324 unsigned int operator()(BB& value) const { return value.val_++; };
325 unsigned int operator()(const BB& value) const { return value.val_; };
326 };
327 bool tm21(Multimethod::entry<unsigned int, Holder, TestMethod2, AA>());
328 bool tm22(Multimethod::entry<unsigned int, Holder, TestMethod2, BB>());
329
330 bool htm21(Holder::entry<TestMethod2, AA>());
331 bool htm22(Holder::entry<TestMethod2, BB>());
332
333 BOOST_AUTO_TEST_CASE(test04)
334 {
335 TestMethod2 m;
336 Holder a0((AA()));
337 BOOST_CHECK_EQUAL(m(a0), 0);
338 BOOST_CHECK_EQUAL(m(a0), 1);
339 BOOST_CHECK_EQUAL(m(a0), 2);
340 BOOST_CHECK_EQUAL(m(a0), 3);
341
342 Holder b0((BB()));
343 BOOST_CHECK_EQUAL(m(b0), 0);
344 BOOST_CHECK_EQUAL(m(b0), 1);
345 BOOST_CHECK_EQUAL(m(b0), 2);
346 BOOST_CHECK_EQUAL(m(b0), 3);
347
348 b0 = a0; // copy AA's instance to b0
349
350 BOOST_CHECK_EQUAL(m(b0), 4);
351 BOOST_CHECK_EQUAL(m(b0), 5);
352 BOOST_CHECK_EQUAL(m(b0), 6);
353 BOOST_CHECK_EQUAL(m(b0), 7);
354 }
355
356
357 BOOST_AUTO_TEST_CASE(test05)
358 {
359 // you can Holder to hold multi method.
360
361 Holder mm;
362
363 mm = TestMethod0();
364 Holder h0(0);
365 BOOST_CHECK_EQUAL(holder_cast<string>(mm(h0)), "int0");
366 Holder h1(0.0);
367 BOOST_CHECK_EQUAL(holder_cast<string>(mm(h1)), "double0");
368 h1 = 0;
369 BOOST_CHECK_EQUAL(holder_cast<string>(mm(h1)), "int0");
370 BOOST_CHECK_EQUAL(holder_cast<string>(mm(h1, h1)), "int0, int0");
371 BOOST_CHECK_EQUAL(holder_cast<string>(mm(h1, h1, h1)), "string(int, int, int)");
372 h1 = 'a';
373 BOOST_CHECK_EQUAL(holder_cast<string>(mm(h1)), "int0");
374
375 mm = TestMethod1(); // copy another multi method to mm.
376 h0 = 0;
377 BOOST_CHECK_EQUAL(holder_cast<string>(mm(h0)), "int1");
378 h1 = 0.0;
379 BOOST_CHECK_EQUAL(holder_cast<string>(mm(h1)), "double1");
380 h1 = 0;
381 BOOST_CHECK_EQUAL(holder_cast<string>(mm(h1)), "int1");
382 h1 = 'a';
383 BOOST_CHECK_EQUAL(holder_cast<string>(mm(h1)), "int1");
384
385 mm = TestVoidMethod(); // copy another void method to mm.
386 h0 = 0;
387 BOOST_CHECK_EQUAL(mm(h0).empty(), true); // return empty Holder.
388
389 mm = TestMethod2();
390 Holder a0((AA()));
391 BOOST_CHECK_EQUAL(holder_cast<unsigned int>(mm(a0)), 0);
392 BOOST_CHECK_EQUAL(holder_cast<unsigned int>(mm(a0)), 1);
393 BOOST_CHECK_EQUAL(holder_cast<unsigned int>(mm(a0)), 2);
394 BOOST_CHECK_EQUAL(holder_cast<unsigned int>(mm(a0)), 3);
395
396 Holder b0((BB()));
397 BOOST_CHECK_EQUAL(holder_cast<unsigned int>(mm(b0)), 0);
398 BOOST_CHECK_EQUAL(holder_cast<unsigned int>(mm(b0)), 1);
399 BOOST_CHECK_EQUAL(holder_cast<unsigned int>(mm(b0)), 2);
400 BOOST_CHECK_EQUAL(holder_cast<unsigned int>(mm(b0)), 3);
401
402 BOOST_CHECK_EQUAL(holder_cast<unsigned int>(mm(a0)), 4);
403 BOOST_CHECK_EQUAL(holder_cast<unsigned int>(mm(a0)), 5);
404 BOOST_CHECK_EQUAL(holder_cast<unsigned int>(mm(a0)), 6);
405 BOOST_CHECK_EQUAL(holder_cast<unsigned int>(mm(a0)), 7);
406 }
407}
408
409
410namespace TestHolderConstruct {
411 BOOST_AUTO_TEST_CASE(test)
412 {
413 // direct construction using https://svn.boost.org/trac/boost/ticket/2748
414 Holder h0;
415 h0.reset<int>();
416 BOOST_CHECK_EQUAL(holder_cast<int>(h0), 0);
417 h0.reset<double>();
418 BOOST_CHECK_EQUAL(holder_cast<double>(h0), 0.0);
419 h0.reset<shared_ptr<int> >();
420 BOOST_CHECK_EQUAL(holder_cast<shared_ptr<int> >(h0).get(), static_cast<int*>(0));
421
422 h0.reset<int>(1);
423 BOOST_CHECK_EQUAL(holder_cast<int>(h0), 1);
424 h0.reset<double>(1);
425 BOOST_CHECK_EQUAL(holder_cast<double>(h0), 1.0);
426
427 h0.reset<tuple<int, double, char> >(1, 2, 'a');
428 BOOST_CHECK_EQUAL((holder_cast<tuple<int, double, char> >(h0).get<0>()), 1);
429 BOOST_CHECK_EQUAL((holder_cast<tuple<int, double, char> >(h0).get<1>()), 2.0);
430 BOOST_CHECK_EQUAL((holder_cast<tuple<int, double, char> >(h0).get<2>()), 'a');
431 }
432}
433
434BOOST_AUTO_TEST_SUITE_END()