Ticket #2748: any.hpp

File any.hpp, 9.3 KB (added by nowake@…, 14 years ago)

modified boost::any

Line 
1// See http://www.boost.org/libs/any for Documentation.
2
3#ifndef BOOST_ANY_INCLUDED
4#define BOOST_ANY_INCLUDED
5
6// what: variant type boost::any
7// who: contributed by Kevlin Henney,
8// with features contributed and bugs found by
9// Ed Brey, Mark Rodgers, Peter Dimov, and James Curran
10// when: July 2001
11// where: tested with BCC 5.5, MSVC 6.0, and g++ 2.95
12
13// Modified to implement "reset" by Nowake
14// and tested with MSVC 8.0
15
16#include <algorithm>
17#include <typeinfo>
18
19#include "boost/config.hpp"
20#include <boost/type_traits/remove_reference.hpp>
21#include <boost/type_traits/is_reference.hpp>
22#include <boost/throw_exception.hpp>
23#include <boost/static_assert.hpp>
24
25namespace boost
26{
27 class any
28 {
29 public: // structors
30
31 any()
32 : content(0)
33 {
34 }
35
36 template<typename ValueType>
37 any(const ValueType & value)
38 : content(new backet<ValueType, true>(value))
39 {
40 }
41
42 any(const any & other)
43 : content(other.content ? other.content->clone() : 0)
44 {
45 }
46
47 ~any()
48 {
49 delete content;
50 }
51
52 public: // modifiers
53
54 any & swap(any & rhs)
55 {
56 std::swap(content, rhs.content);
57 return *this;
58 }
59
60 template<typename ValueType>
61 any & operator=(const ValueType & rhs)
62 {
63 any(rhs).swap(*this);
64 return *this;
65 }
66
67 any & operator=(any rhs)
68 {
69 rhs.swap(*this);
70 return *this;
71 }
72 public:
73
74 void reset()
75 {
76 any().swap(*this);
77 }
78
79
80 template<typename ValueType, bool copyable>
81 void reset()
82 {
83 std::auto_ptr<backet<ValueType, copyable> > h(new backet<ValueType, copyable>());
84 any t;
85 t.content = h.release();
86 t.swap(*this);
87 };
88
89 template<typename ValueType>
90 void reset()
91 {
92 reset<ValueType, true>();
93 };
94
95
96 template<typename ValueType, bool copyable, typename ArgumentType1>
97 void reset(const ArgumentType1& argument1)
98 {
99 std::auto_ptr<backet<ValueType, copyable> > h(new backet<ValueType, copyable>(argument1));
100 any t;
101 t.content = h.release();
102 t.swap(*this);
103 };
104
105 template<typename ValueType, typename ArgumentType1>
106 void reset(const ArgumentType1& argument1)
107 {
108 reset<ValueType, true>(argument1);
109 };
110
111
112 template<typename ValueType, bool copyable, typename ArgumentType1, typename ArgumentType2>
113 void reset(const ArgumentType1& argument1, const ArgumentType2& argument2)
114 {
115 std::auto_ptr<backet<ValueType, copyable> > h(new backet<ValueType, copyable>(argument1, argument2));
116 any t;
117 t.content = h.release();
118 t.swap(*this);
119 };
120
121 template<typename ValueType, typename ArgumentType1, typename ArgumentType2>
122 void reset(const ArgumentType1& argument1, const ArgumentType2& argument2)
123 {
124 reset<ValueType, true>(argument1, argument2);
125 };
126
127 public: // queries
128
129 bool empty() const
130 {
131 return !content;
132 }
133
134 const std::type_info & type() const
135 {
136 return content ? content->type() : typeid(void);
137 }
138
139#ifndef BOOST_NO_MEMBER_TEMPLATE_FRIENDS
140 private: // types
141#else
142 public: // types (public so any_cast can be non-friend)
143#endif
144
145 class placeholder
146 {
147 public: // structors
148
149 virtual ~placeholder()
150 {
151 }
152
153 public: // queries
154
155 virtual const std::type_info & type() const = 0;
156
157 virtual placeholder * clone() const = 0;
158
159 };
160
161 template<typename ValueType>
162 class holder : public placeholder
163 {
164 public: // structors
165
166 holder(const ValueType & value)
167 : held(value)
168 {
169 }
170
171 public:
172
173 template<typename ArgumentType1>
174 holder(const ArgumentType1& argument1)
175 : held(argument1)
176 {
177 }
178
179
180 template<typename ArgumentType1, typename ArgumentType2>
181 holder(const ArgumentType1& argument1, const ArgumentType2& argument2)
182 : held(argument1, argument2)
183 {
184 }
185
186
187 public: // queries
188
189 virtual const std::type_info & type() const
190 {
191 return typeid(ValueType);
192 }
193
194
195 public: // representation
196
197 ValueType held;
198
199 private: // intentionally left unimplemented
200 holder & operator=(const holder &);
201 };
202
203
204 //template<typename ValueType>
205 template<typename ValueType, bool copyable>
206 class backet : public holder<ValueType>
207 {
208 public: // structors
209 backet(const ValueType & value)
210 : holder(value)
211 {
212 }
213
214 public:
215
216 template<typename ArgumentType1>
217 backet(const ArgumentType1& argument1)
218 : holder(argument1)
219 {
220 }
221
222 template<typename ArgumentType1, typename ArgumentType2>
223 backet(const ArgumentType1& argument1, const ArgumentType2& argument2)
224 : holder(argument1, argument2)
225 {
226 }
227
228 template<bool copyable>
229 struct creator {
230 static placeholder* clone(const ValueType& value) {
231 return new backet(value);
232 }
233 };
234 template<>
235 struct creator<false> {
236 static placeholder* clone(const ValueType& value) {
237 throw "error";
238 }
239 };
240
241 virtual placeholder * clone() const
242 {
243 //return new holder(held);
244 return creator<copyable>::clone(held);
245 }
246
247
248 };
249#ifndef BOOST_NO_MEMBER_TEMPLATE_FRIENDS
250
251 private: // representation
252
253 template<typename ValueType>
254 friend ValueType * any_cast(any *);
255
256 template<typename ValueType>
257 friend ValueType * unsafe_any_cast(any *);
258
259#else
260
261 public: // representation (public so any_cast can be non-friend)
262
263#endif
264
265 placeholder * content;
266
267 };
268
269 class bad_any_cast : public std::bad_cast
270 {
271 public:
272 virtual const char * what() const throw()
273 {
274 return "boost::bad_any_cast: "
275 "failed conversion using boost::any_cast";
276 }
277 };
278
279 template<typename ValueType>
280 ValueType * any_cast(any * operand)
281 {
282 return operand && operand->type() == typeid(ValueType)
283 ? &static_cast<any::holder<ValueType> *>(operand->content)->held
284 : 0;
285 }
286
287 template<typename ValueType>
288 inline const ValueType * any_cast(const any * operand)
289 {
290 return any_cast<ValueType>(const_cast<any *>(operand));
291 }
292
293 template<typename ValueType>
294 ValueType any_cast(any & operand)
295 {
296 typedef BOOST_DEDUCED_TYPENAME remove_reference<ValueType>::type nonref;
297
298#ifdef BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION
299 // If 'nonref' is still reference type, it means the user has not
300 // specialized 'remove_reference'.
301
302 // Please use BOOST_BROKEN_COMPILER_TYPE_TRAITS_SPECIALIZATION macro
303 // to generate specialization of remove_reference for your class
304 // See type traits library documentation for details
305 BOOST_STATIC_ASSERT(!is_reference<nonref>::value);
306#endif
307
308 nonref * result = any_cast<nonref>(&operand);
309 if(!result)
310 boost::throw_exception(bad_any_cast());
311 return *result;
312 }
313
314 template<typename ValueType>
315 inline ValueType any_cast(const any & operand)
316 {
317 typedef BOOST_DEDUCED_TYPENAME remove_reference<ValueType>::type nonref;
318
319#ifdef BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION
320 // The comment in the above version of 'any_cast' explains when this
321 // assert is fired and what to do.
322 BOOST_STATIC_ASSERT(!is_reference<nonref>::value);
323#endif
324
325 return any_cast<const nonref &>(const_cast<any &>(operand));
326 }
327
328 // Note: The "unsafe" versions of any_cast are not part of the
329 // public interface and may be removed at any time. They are
330 // required where we know what type is stored in the any and can't
331 // use typeid() comparison, e.g., when our types may travel across
332 // different shared libraries.
333 template<typename ValueType>
334 inline ValueType * unsafe_any_cast(any * operand)
335 {
336 return &static_cast<any::holder<ValueType> *>(operand->content)->held;
337 }
338
339 template<typename ValueType>
340 inline const ValueType * unsafe_any_cast(const any * operand)
341 {
342 return unsafe_any_cast<ValueType>(const_cast<any *>(operand));
343 }
344}
345
346// Copyright Kevlin Henney, 2000, 2001, 2002. All rights reserved.
347//
348// Distributed under the Boost Software License, Version 1.0. (See
349// accompanying file LICENSE_1_0.txt or copy at
350// http://www.boost.org/LICENSE_1_0.txt)
351
352#endif