1// Boost.TypeErasure library
2//
3// Copyright 2015 Steven Watanabe
4//
5// Distributed under the Boost Software License Version 1.0. (See
6// accompanying file LICENSE_1_0.txt or copy at
7// http://www.boost.org/LICENSE_1_0.txt)
8//
9// $Id$
10
11#include <boost/type_erasure/any.hpp>
12#include <boost/type_erasure/builtin.hpp>
13#include <boost/type_erasure/operators.hpp>
14#include <boost/type_erasure/dynamic_any_cast.hpp>
15#include <boost/type_erasure/any_cast.hpp>
16#include <boost/mpl/vector.hpp>
17#include <boost/mpl/map.hpp>
18
19#define BOOST_TEST_MAIN
20#include <boost/test/unit_test.hpp>
21
22using namespace boost::type_erasure;
23
24template<class T = _self>
25struct common : ::boost::mpl::vector<
26 copy_constructible<T>,
27 typeid_<T>
28> {};
29
30struct fixture
31{
32 fixture()
33 {
34 register_binding<common<>, int>();
35 register_binding<incrementable<>, int>();
36 register_binding<addable<_self, _self, _a> >(make_binding<boost::mpl::map<boost::mpl::pair<_self, int>, boost::mpl::pair<_a, int> > >());
37 }
38};
39
40BOOST_GLOBAL_FIXTURE(fixture);
41
42BOOST_AUTO_TEST_CASE(test_identical)
43{
44 any<common<> > x(1);
45 any<common<> > y = dynamic_any_cast<any<common<> > >(arg&: x);
46 BOOST_CHECK_EQUAL(any_cast<int>(y), 1);
47}
48
49BOOST_AUTO_TEST_CASE(test_downcast)
50{
51 any<common<> > x(1);
52 typedef any< ::boost::mpl::vector<common<>, incrementable<> > > incrementable_any;
53 incrementable_any y = dynamic_any_cast<incrementable_any>(arg&: x);
54 ++y;
55 BOOST_CHECK_EQUAL(any_cast<int>(y), 2);
56}
57
58BOOST_AUTO_TEST_CASE(test_cross_cast)
59{
60 any< ::boost::mpl::vector<common<>, decrementable<> > > x(1);
61 typedef any< ::boost::mpl::vector<common<>, incrementable<> > > incrementable_any;
62 incrementable_any y = dynamic_any_cast<incrementable_any>(arg&: x);
63 ++y;
64 BOOST_CHECK_EQUAL(any_cast<int>(y), 2);
65}
66
67BOOST_AUTO_TEST_CASE(test_cast_placeholder)
68{
69 any<common<> > x(1);
70 typedef any< ::boost::mpl::vector<common<_a>, incrementable<_a> >, _a> incrementable_any;
71 incrementable_any y = dynamic_any_cast<incrementable_any>(arg&: x);
72 ++y;
73 BOOST_CHECK_EQUAL(any_cast<int>(y), 2);
74}
75
76BOOST_AUTO_TEST_CASE(test_throw)
77{
78 any<common<> > x("42");
79 typedef any< ::boost::mpl::vector<common<_a>, incrementable<_a> >, _a> incrementable_any;
80 BOOST_CHECK_THROW(dynamic_any_cast<incrementable_any>(x), bad_any_cast);
81}
82
83// make sure that a function registered with _self can
84// be found with _a.
85BOOST_AUTO_TEST_CASE(test_other_placeholder)
86{
87 any<common<_a>, _a> x(1);
88 typedef any< ::boost::mpl::vector<common<_a>, incrementable<_a> >, _a> incrementable_any;
89 incrementable_any y = dynamic_any_cast<incrementable_any>(arg&: x);
90 ++y;
91 BOOST_CHECK_EQUAL(any_cast<int>(y), 2);
92}
93
94// Casting to a value only requires the target to provide
95// a copy constructor.
96BOOST_AUTO_TEST_CASE(test_add_copy)
97{
98 any< ::boost::mpl::vector<destructible<>, typeid_<> > > x(1);
99 any<common<> > y = dynamic_any_cast<any<common<> > >(arg&: x);
100 BOOST_CHECK_EQUAL(any_cast<int>(y), 1);
101}
102
103template<class T, class U>
104struct choose_second
105{
106 typedef U type;
107};
108
109BOOST_AUTO_TEST_CASE(test_deduced)
110{
111 typedef deduced<choose_second<_self, int> > _p2;
112 any< ::boost::mpl::vector<common<>, common<_p2> > > x(1);
113 typedef ::boost::mpl::vector<common<>, common<_p2>, incrementable<_p2>, addable<_self, _self, _p2> > dest_concept;
114 any<dest_concept> y = dynamic_any_cast<any<dest_concept> >(arg&: x);
115 any<dest_concept, _p2> z = y + y;
116 ++z;
117 BOOST_CHECK_EQUAL(any_cast<int>(z), 3);
118}
119
120BOOST_AUTO_TEST_CASE(test_multiple_placeholders)
121{
122 typedef ::boost::mpl::map< ::boost::mpl::pair<_a, int>, boost::mpl::pair<_b, int> > init_map;
123 any< ::boost::mpl::vector<common<_a>, common<_b> >, _a> x(1, make_binding<init_map>());
124 typedef ::boost::mpl::vector<common<_a>, common<_b>, incrementable<_b>, addable<_a, _a, _b> > dest_concept;
125 typedef ::boost::mpl::map< ::boost::mpl::pair<_a, _a>, ::boost::mpl::pair<_b, _b> > placeholder_map;
126 any<dest_concept, _a> y = dynamic_any_cast<any<dest_concept, _a> >(arg&: x, map: make_binding<placeholder_map>());
127 any<dest_concept, _b> z = y + y;
128 ++z;
129 BOOST_CHECK_EQUAL(any_cast<int>(z), 3);
130}
131
132BOOST_AUTO_TEST_CASE(test_multiple_placeholders_switch)
133{
134 typedef ::boost::mpl::map< ::boost::mpl::pair<_a, int>, boost::mpl::pair<_b, int> > init_map;
135 any< ::boost::mpl::vector<common<_a>, common<_b> >, _a> x(1, make_binding<init_map>());
136 typedef ::boost::mpl::vector<common<_c>, common<_d>, incrementable<_d>, addable<_c, _c, _d> > dest_concept;
137 typedef ::boost::mpl::map< ::boost::mpl::pair<_c, _a>, ::boost::mpl::pair<_d, _b> > placeholder_map;
138 any<dest_concept, _c> y = dynamic_any_cast<any<dest_concept, _c> >(arg&: x, map: make_binding<placeholder_map>());
139 any<dest_concept, _d> z = y + y;
140 ++z;
141 BOOST_CHECK_EQUAL(any_cast<int>(z), 3);
142}
143
144template<class T>
145T as_rvalue(const T& arg) { return arg; }
146template<class T>
147const T& as_const(const T& arg) { return arg; }
148
149BOOST_AUTO_TEST_CASE(test_val)
150{
151 any<common<> > x(1);
152 // value
153 any<common<> > y1 = dynamic_any_cast<any<common<> > >(arg&: x);
154 BOOST_CHECK_EQUAL(any_cast<int>(x), any_cast<int>(y1));
155 any<common<> > y2 = dynamic_any_cast<any<common<> > >(arg: as_rvalue(arg: x));
156 BOOST_CHECK_EQUAL(any_cast<int>(x), any_cast<int>(y2));
157 any<common<> > y3 = dynamic_any_cast<any<common<> > >(arg: as_const(arg: x));
158 BOOST_CHECK_EQUAL(any_cast<int>(x), any_cast<int>(y3));
159
160 // lvalue reference
161 any<common<>, _self&> r(x);
162 any<common<> > z1 = dynamic_any_cast<any<common<> > >(arg&: r);
163 BOOST_CHECK_EQUAL(any_cast<int>(x), any_cast<int>(z1));
164 any<common<> > z2 = dynamic_any_cast<any<common<> > >(arg: as_rvalue(arg: r));
165 BOOST_CHECK_EQUAL(any_cast<int>(x), any_cast<int>(z2));
166 any<common<> > z3 = dynamic_any_cast<any<common<> > >(arg: as_const(arg: r));
167 BOOST_CHECK_EQUAL(any_cast<int>(x), any_cast<int>(z3));
168
169 // const reference
170 any<common<>, const _self&> cr(x);
171 any<common<> > w1 = dynamic_any_cast<any<common<> > >(arg&: cr);
172 BOOST_CHECK_EQUAL(any_cast<int>(x), any_cast<int>(w1));
173 any<common<> > w2 = dynamic_any_cast<any<common<> > >(arg: as_rvalue(arg: cr));
174 BOOST_CHECK_EQUAL(any_cast<int>(x), any_cast<int>(w2));
175 any<common<> > w3 = dynamic_any_cast<any<common<> > >(arg: as_const(arg: cr));
176 BOOST_CHECK_EQUAL(any_cast<int>(x), any_cast<int>(w3));
177
178#ifndef BOOST_NO_CXX11_RVALUE_REFERENCES
179 // rvalue reference
180 any<common<>, _self&&> rr(std::move(x));
181 any<common<> > v1 = dynamic_any_cast<any<common<> > >(arg&: rr);
182 BOOST_CHECK_EQUAL(any_cast<int>(x), any_cast<int>(v1));
183 any<common<> > v2 = dynamic_any_cast<any<common<> > >(arg: as_rvalue(arg: rr));
184 BOOST_CHECK_EQUAL(any_cast<int>(x), any_cast<int>(v2));
185 any<common<> > v3 = dynamic_any_cast<any<common<> > >(arg: as_const(arg: rr));
186 BOOST_CHECK_EQUAL(any_cast<int>(x), any_cast<int>(v3));
187#endif
188}
189
190BOOST_AUTO_TEST_CASE(test_ref)
191{
192 // A non-const reference can only bind to a few cases
193 any<common<> > x(1);
194 any<common<>, _self&> y = dynamic_any_cast<any<common<>, _self&> >(arg&: x);
195 BOOST_CHECK_EQUAL(any_cast<int*>(&x), any_cast<int*>(&y));
196
197 any<common<>, _self&> z = dynamic_any_cast<any<common<>, _self&> >(arg&: y);
198 BOOST_CHECK_EQUAL(any_cast<int*>(&x), any_cast<int*>(&z));
199 any<common<>, _self&> w = dynamic_any_cast<any<common<>, _self&> >(arg: as_rvalue(arg: y));
200 BOOST_CHECK_EQUAL(any_cast<int*>(&x), any_cast<int*>(&w));
201 any<common<>, _self&> v = dynamic_any_cast<any<common<>, _self&> >(arg: as_const(arg: y));
202 BOOST_CHECK_EQUAL(any_cast<int*>(&x), any_cast<int*>(&v));
203}
204
205BOOST_AUTO_TEST_CASE(test_cref)
206{
207 any<common<> > x(1);
208 typedef any<common<>, const _self&> dest_type;
209
210 // value
211 dest_type y1 = dynamic_any_cast<dest_type>(arg&: x);
212 BOOST_CHECK_EQUAL(any_cast<const int*>(&x), any_cast<const int*>(&y1));
213 // as_rvalue creates a temporary
214 BOOST_CHECK_EQUAL(any_cast<int>(x), any_cast<int>(dynamic_any_cast<dest_type>(as_rvalue(x))));
215 dest_type y3 = dynamic_any_cast<dest_type>(arg: as_const(arg: x));
216 BOOST_CHECK_EQUAL(any_cast<const int*>(&x), any_cast<const int*>(&y3));
217
218 // lvalue reference
219 any<common<>, _self&> r(x);
220 dest_type z1 = dynamic_any_cast<dest_type>(arg&: r);
221 BOOST_CHECK_EQUAL(any_cast<const int*>(&x), any_cast<const int*>(&z1));
222 dest_type z2 = dynamic_any_cast<dest_type>(arg: as_rvalue(arg: r));
223 BOOST_CHECK_EQUAL(any_cast<const int*>(&x), any_cast<const int*>(&z2));
224 dest_type z3 = dynamic_any_cast<dest_type>(arg: as_const(arg: r));
225 BOOST_CHECK_EQUAL(any_cast<const int*>(&x), any_cast<const int*>(&z3));
226
227 // const reference
228 any<common<>, const _self&> cr(x);
229 dest_type w1 = dynamic_any_cast<dest_type>(arg&: cr);
230 BOOST_CHECK_EQUAL(any_cast<const int*>(&x), any_cast<const int*>(&w1));
231 dest_type w2 = dynamic_any_cast<dest_type>(arg: as_rvalue(arg: cr));
232 BOOST_CHECK_EQUAL(any_cast<const int*>(&x), any_cast<const int*>(&w2));
233 dest_type w3 = dynamic_any_cast<dest_type>(arg: as_const(arg: cr));
234 BOOST_CHECK_EQUAL(any_cast<const int*>(&x), any_cast<const int*>(&w3));
235
236#ifndef BOOST_NO_CXX11_RVALUE_REFERENCES
237 // rvalue reference
238 any<common<>, _self&&> rr(std::move(x));
239 dest_type v1 = dynamic_any_cast<dest_type>(arg&: rr);
240 BOOST_CHECK_EQUAL(any_cast<const int*>(&x), any_cast<const int*>(&v1));
241 dest_type v2 = dynamic_any_cast<dest_type>(arg: as_rvalue(arg: rr));
242 BOOST_CHECK_EQUAL(any_cast<const int*>(&x), any_cast<const int*>(&v2));
243 dest_type v3 = dynamic_any_cast<dest_type>(arg: as_const(arg: rr));
244 BOOST_CHECK_EQUAL(any_cast<const int*>(&x), any_cast<const int*>(&v3));
245#endif
246}
247
248#ifndef BOOST_NO_CXX11_RVALUE_REFERENCES
249
250BOOST_AUTO_TEST_CASE(test_rref)
251{
252 any<common<> > x(1);
253 typedef any<common<>, _self&&> dest_type;
254
255 // value
256 dest_type y2 = dynamic_any_cast<dest_type>(arg: std::move(x));
257 BOOST_CHECK_EQUAL(any_cast<int*>(&x), any_cast<int*>(&y2));
258
259 // rvalue reference
260 any<common<>, _self&&> rr(std::move(x));
261 dest_type v2 = dynamic_any_cast<dest_type>(arg: std::move(rr));
262 BOOST_CHECK_EQUAL(any_cast<int*>(&x), any_cast<int*>(&v2));
263}
264
265#endif
266

source code of boost/libs/type_erasure/test/test_dynamic_any_cast.cpp