1 | // Boost.TypeErasure library |
2 | // |
3 | // Copyright 2011 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/config.hpp> |
12 | |
13 | #ifdef BOOST_MSVC |
14 | #pragma warning(disable:4244) // conversion from double to int |
15 | #endif |
16 | |
17 | #include <boost/type_erasure/any.hpp> |
18 | #include <boost/type_erasure/tuple.hpp> |
19 | #include <boost/type_erasure/builtin.hpp> |
20 | #include <boost/type_erasure/operators.hpp> |
21 | #include <boost/type_erasure/any_cast.hpp> |
22 | #include <boost/type_erasure/relaxed.hpp> |
23 | #include <boost/mpl/vector.hpp> |
24 | |
25 | #define BOOST_TEST_MAIN |
26 | #include <boost/test/unit_test.hpp> |
27 | |
28 | using namespace boost::type_erasure; |
29 | using boost::core::demangle; |
30 | |
31 | template<class T = _self> |
32 | struct common : ::boost::mpl::vector< |
33 | copy_constructible<T>, |
34 | typeid_<T> |
35 | > {}; |
36 | |
37 | #ifndef BOOST_NO_CXX11_RVALUE_REFERENCES |
38 | |
39 | template<class T = _self> |
40 | struct movable_common : ::boost::mpl::vector< |
41 | destructible<T>, |
42 | constructible<T(T&&)>, |
43 | typeid_<T> |
44 | > {}; |
45 | |
46 | template<class T = _self, class U = T> |
47 | struct move_assignable : ::boost::mpl::vector< |
48 | assignable<T, U&&> |
49 | > {}; |
50 | |
51 | #endif |
52 | |
53 | template<class T, bool CCtor, bool MoveCtor, bool CAssign, bool MoveAssign> |
54 | struct test_class |
55 | { |
56 | explicit test_class(T n) : value(n) {} |
57 | test_class(const test_class& src) : value(src.value) |
58 | { |
59 | BOOST_STATIC_ASSERT_MSG(CCtor, "Copy constructor not allowed." ); |
60 | } |
61 | test_class& operator=(const test_class& src) |
62 | { |
63 | BOOST_STATIC_ASSERT_MSG(CAssign, "Copy assignment not allowed." ); |
64 | value = src.value; |
65 | return *this; |
66 | } |
67 | #ifndef BOOST_NO_CXX11_RVALUE_REFERENCES |
68 | test_class(test_class&& src) : value(src.value) |
69 | { |
70 | BOOST_STATIC_ASSERT_MSG(MoveCtor, "Move constructor not allowed." ); |
71 | src.value = 0; |
72 | } |
73 | test_class& operator=(test_class&& src) |
74 | { |
75 | BOOST_STATIC_ASSERT_MSG(MoveAssign, "Move assignment not allowed." ); |
76 | value = src.value; |
77 | src.value = 0; |
78 | return *this; |
79 | } |
80 | #endif |
81 | bool operator==(T n) const { return value == n; } |
82 | T value; |
83 | }; |
84 | |
85 | template<class T, bool CCtor, bool MoveCtor, bool CAssign, bool MoveAssign> |
86 | std::ostream& operator<<(std::ostream& os, const test_class<T, CCtor, MoveCtor, CAssign, MoveAssign>& t) |
87 | { |
88 | return os << t.value; |
89 | } |
90 | |
91 | enum copy_info { |
92 | id_lvalue = 1, |
93 | id_const_lvalue = 2, |
94 | #ifndef BOOST_NO_CXX11_RVALUE_REFERENCES |
95 | id_rvalue = 3, |
96 | id_maybe_const_lvalue = id_lvalue, // used for the id of construction from a raw value |
97 | #else |
98 | id_rvalue = id_const_lvalue, |
99 | id_maybe_const_lvalue = id_const_lvalue, |
100 | #endif |
101 | id_construct = 4, |
102 | id_assign = 8, |
103 | id_copy = 16, |
104 | id_int = 32 |
105 | }; |
106 | |
107 | #ifdef BOOST_MSVC |
108 | #pragma warning(disable:4521) // multiple copy constructors specified |
109 | #pragma warning(disable:4522) // multiple assignment operators specified |
110 | #endif |
111 | |
112 | template<class T> |
113 | struct copy_tracker |
114 | { |
115 | copy_tracker(const copy_tracker& src) : value(src.value), info(id_const_lvalue | id_construct | id_copy), moved_from(false) {} |
116 | copy_tracker(copy_tracker& src) : value(src.value), info(id_lvalue | id_construct | id_copy), moved_from(false) {} |
117 | copy_tracker& operator=(const copy_tracker& src) { value = (src.value); info = (id_const_lvalue | id_assign | id_copy); moved_from = false; return *this; } |
118 | copy_tracker& operator=(copy_tracker& src) { value = (src.value); info = (id_lvalue | id_assign | id_copy); moved_from = false; return *this; } |
119 | copy_tracker(const T& src) : value(src), info(id_const_lvalue | id_construct | id_int), moved_from(false) {} |
120 | copy_tracker(T& src) : value(src), info(id_lvalue | id_construct | id_int), moved_from(false) {} |
121 | copy_tracker& operator=(const T& src) { value = (src); info = (id_const_lvalue | id_assign | id_int); moved_from = false; return *this; } |
122 | copy_tracker& operator=(T& src) { value = (src); info = (id_lvalue | id_assign | id_int); moved_from = false; return *this; } |
123 | #ifndef BOOST_NO_CXX11_RVALUE_REFERENCES |
124 | copy_tracker(copy_tracker&& src) : value(std::move(src.value)), info(id_rvalue | id_construct | id_copy), moved_from(false) { src.moved_from = true; } |
125 | copy_tracker& operator=(copy_tracker&& src) { value = std::move(src.value); info = (id_rvalue | id_assign | id_copy); moved_from = false; src.moved_from = true; return *this; } |
126 | copy_tracker(T&& src) : value(std::move(src)), info(id_rvalue | id_construct | id_int), moved_from(false) {} |
127 | copy_tracker& operator=(T&& src) { value = std::move(src); info = (id_rvalue | id_assign | id_int); moved_from = false; return *this; } |
128 | #endif |
129 | template<class U> |
130 | explicit copy_tracker(const U& src) : value(src), info(id_const_lvalue | id_construct | id_int), moved_from(false) {} |
131 | T value; |
132 | int info; |
133 | bool moved_from; |
134 | }; |
135 | |
136 | template<class T> |
137 | struct value_holder |
138 | { |
139 | typedef copy_tracker<T> type; |
140 | typedef copy_tracker<T> unwrapped_type; |
141 | template<class U> |
142 | value_holder(const U& u) : value(u) {} |
143 | type value; |
144 | type get() { return value; } |
145 | const unwrapped_type& unwrap() { return value; } |
146 | template<class U> |
147 | const U& unwrap() { return value; } |
148 | }; |
149 | |
150 | template<class C, class P> |
151 | struct value_holder<any<C, P> > |
152 | { |
153 | typedef any<C, P> type; |
154 | typedef any<C, P> unwrapped_type; |
155 | #ifndef BOOST_NO_CXX11_RVALUE_REFERENCES |
156 | template<class U> |
157 | value_holder(U&& u) : value(std::forward<U>(u)) {} |
158 | #else |
159 | template<class U> |
160 | value_holder(U& u) : value(u) {} |
161 | template<class U> |
162 | value_holder(const U& u) : value(u) {} |
163 | #endif |
164 | type value; |
165 | type get() { return value; } |
166 | const unwrapped_type& unwrap() { return value; } |
167 | template<class U> |
168 | const U& unwrap() { return any_cast<const U&>(value); } |
169 | }; |
170 | |
171 | template<class T> |
172 | struct value_holder<T&> |
173 | { |
174 | typedef typename value_holder<T>::type& type; |
175 | typedef typename value_holder<T>::unwrapped_type unwrapped_type; |
176 | #ifndef BOOST_NO_CXX11_RVALUE_REFERENCES |
177 | template<class U> |
178 | value_holder(U&& u) : impl(std::forward<U>(u)) {} |
179 | #else |
180 | template<class U> |
181 | value_holder(U& u) : impl(u) {} |
182 | template<class U> |
183 | value_holder(const U& u) : impl(u) {} |
184 | #endif |
185 | value_holder<T> impl; |
186 | type get() { return impl.value; } |
187 | const unwrapped_type& unwrap() { return unwrap<unwrapped_type>(); } |
188 | template<class U> |
189 | const U& unwrap() { return impl.template unwrap<unwrapped_type>(); } |
190 | }; |
191 | |
192 | template<class T> |
193 | struct value_holder<const T&> |
194 | { |
195 | typedef const typename value_holder<T>::type& type; |
196 | typedef typename value_holder<T>::unwrapped_type unwrapped_type; |
197 | #ifndef BOOST_NO_CXX11_RVALUE_REFERENCES |
198 | template<class U> |
199 | value_holder(U&& u) : impl(std::forward<U>(u)) {} |
200 | #else |
201 | template<class U> |
202 | value_holder(U& u) : impl(u) {} |
203 | template<class U> |
204 | value_holder(const U& u) : impl(u) {} |
205 | #endif |
206 | value_holder<T> impl; |
207 | type get() { return impl.value; } |
208 | const unwrapped_type& unwrap() { return unwrap<unwrapped_type>(); } |
209 | template<class U> |
210 | const U& unwrap() { return impl.template unwrap<unwrapped_type>(); } |
211 | }; |
212 | |
213 | #ifndef BOOST_NO_CXX11_RVALUE_REFERENCES |
214 | |
215 | template<class T> |
216 | struct value_holder<T&&> |
217 | { |
218 | typedef typename value_holder<T>::type&& type; |
219 | typedef typename value_holder<T>::unwrapped_type unwrapped_type; |
220 | template<class U> |
221 | value_holder(U&& u) : impl(std::forward<U>(u)) {} |
222 | value_holder<T> impl; |
223 | type get() { return std::move(impl.value); } |
224 | const unwrapped_type& unwrap() { return unwrap<unwrapped_type>(); } |
225 | template<class U> |
226 | const U& unwrap() { return impl.template unwrap<unwrapped_type>(); } |
227 | }; |
228 | |
229 | #endif |
230 | |
231 | template<class T, class A> |
232 | struct value_holder<T(A)> |
233 | { |
234 | #ifndef BOOST_NO_CXX11_RVALUE_REFERENCES |
235 | template<class U> |
236 | value_holder(U&& u) : init(std::forward<U>(u)), impl(init.get()) {} |
237 | #else |
238 | template<class U> |
239 | value_holder(U& u) : init(u), impl(init.get()) {} |
240 | template<class U> |
241 | value_holder(const U& u) : init(u), impl(init.get()) {} |
242 | #endif |
243 | value_holder<A> init; |
244 | value_holder<T> impl; |
245 | typedef typename value_holder<T>::type type; |
246 | typedef typename value_holder<A>::unwrapped_type unwrapped_type; |
247 | type get() { return impl.get(); } |
248 | const unwrapped_type& unwrap() { return unwrap<unwrapped_type>(); } |
249 | template<class U> |
250 | const U& unwrap() { return impl.template unwrap<unwrapped_type>(); } |
251 | }; |
252 | |
253 | #define TEST_ASSIGNMENT_I(LHS, RHS, result, ptr_op, R) \ |
254 | try \ |
255 | { \ |
256 | value_holder<LHS> |
---|