|
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 #include <algorithm> |
|
14 #include <typeinfo> |
|
15 |
|
16 #include "boost/config.hpp" |
|
17 #include <boost/type_traits/remove_reference.hpp> |
|
18 #include <boost/type_traits/is_reference.hpp> |
|
19 #include <boost/throw_exception.hpp> |
|
20 #include <boost/static_assert.hpp> |
|
21 |
|
22 namespace boost |
|
23 { |
|
24 class any |
|
25 { |
|
26 public: // structors |
|
27 |
|
28 any() |
|
29 : content(0) |
|
30 { |
|
31 } |
|
32 |
|
33 template<typename ValueType> |
|
34 any(const ValueType & value) |
|
35 : content(new holder<ValueType>(value)) |
|
36 { |
|
37 } |
|
38 |
|
39 any(const any & other) |
|
40 : content(other.content ? other.content->clone() : 0) |
|
41 { |
|
42 } |
|
43 |
|
44 ~any() |
|
45 { |
|
46 delete content; |
|
47 } |
|
48 |
|
49 public: // modifiers |
|
50 |
|
51 any & swap(any & rhs) |
|
52 { |
|
53 std::swap(content, rhs.content); |
|
54 return *this; |
|
55 } |
|
56 |
|
57 template<typename ValueType> |
|
58 any & operator=(const ValueType & rhs) |
|
59 { |
|
60 any(rhs).swap(*this); |
|
61 return *this; |
|
62 } |
|
63 |
|
64 any & operator=(const any & rhs) |
|
65 { |
|
66 any(rhs).swap(*this); |
|
67 return *this; |
|
68 } |
|
69 |
|
70 public: // queries |
|
71 |
|
72 bool empty() const |
|
73 { |
|
74 return !content; |
|
75 } |
|
76 |
|
77 const std::type_info & type() const |
|
78 { |
|
79 return content ? content->type() : typeid(void); |
|
80 } |
|
81 |
|
82 #ifndef BOOST_NO_MEMBER_TEMPLATE_FRIENDS |
|
83 private: // types |
|
84 #else |
|
85 public: // types (public so any_cast can be non-friend) |
|
86 #endif |
|
87 |
|
88 class placeholder |
|
89 { |
|
90 public: // structors |
|
91 |
|
92 virtual ~placeholder() |
|
93 { |
|
94 } |
|
95 |
|
96 public: // queries |
|
97 |
|
98 virtual const std::type_info & type() const = 0; |
|
99 |
|
100 virtual placeholder * clone() const = 0; |
|
101 |
|
102 }; |
|
103 |
|
104 template<typename ValueType> |
|
105 class holder : public placeholder |
|
106 { |
|
107 public: // structors |
|
108 |
|
109 holder(const ValueType & value) |
|
110 : held(value) |
|
111 { |
|
112 } |
|
113 |
|
114 public: // queries |
|
115 |
|
116 virtual const std::type_info & type() const |
|
117 { |
|
118 return typeid(ValueType); |
|
119 } |
|
120 |
|
121 virtual placeholder * clone() const |
|
122 { |
|
123 return new holder(held); |
|
124 } |
|
125 |
|
126 public: // representation |
|
127 |
|
128 ValueType held; |
|
129 |
|
130 }; |
|
131 |
|
132 #ifndef BOOST_NO_MEMBER_TEMPLATE_FRIENDS |
|
133 |
|
134 private: // representation |
|
135 |
|
136 template<typename ValueType> |
|
137 friend ValueType * any_cast(any *); |
|
138 |
|
139 template<typename ValueType> |
|
140 friend ValueType * unsafe_any_cast(any *); |
|
141 |
|
142 #else |
|
143 |
|
144 public: // representation (public so any_cast can be non-friend) |
|
145 |
|
146 #endif |
|
147 |
|
148 placeholder * content; |
|
149 |
|
150 }; |
|
151 |
|
152 class bad_any_cast : public std::bad_cast |
|
153 { |
|
154 public: |
|
155 virtual const char * what() const throw() |
|
156 { |
|
157 return "boost::bad_any_cast: " |
|
158 "failed conversion using boost::any_cast"; |
|
159 } |
|
160 }; |
|
161 |
|
162 template<typename ValueType> |
|
163 ValueType * any_cast(any * operand) |
|
164 { |
|
165 return operand && operand->type() == typeid(ValueType) |
|
166 ? &static_cast<any::holder<ValueType> *>(operand->content)->held |
|
167 : 0; |
|
168 } |
|
169 |
|
170 template<typename ValueType> |
|
171 const ValueType * any_cast(const any * operand) |
|
172 { |
|
173 return any_cast<ValueType>(const_cast<any *>(operand)); |
|
174 } |
|
175 |
|
176 template<typename ValueType> |
|
177 ValueType any_cast(const any & operand) |
|
178 { |
|
179 typedef BOOST_DEDUCED_TYPENAME remove_reference<ValueType>::type nonref; |
|
180 |
|
181 #ifdef BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION |
|
182 // If 'nonref' is still reference type, it means the user has not |
|
183 // specialized 'remove_reference'. |
|
184 |
|
185 // Please use BOOST_BROKEN_COMPILER_TYPE_TRAITS_SPECIALIZATION macro |
|
186 // to generate specialization of remove_reference for your class |
|
187 // See type traits library documentation for details |
|
188 BOOST_STATIC_ASSERT(!is_reference<nonref>::value); |
|
189 #endif |
|
190 |
|
191 const nonref * result = any_cast<nonref>(&operand); |
|
192 if(!result) |
|
193 boost::throw_exception(bad_any_cast()); |
|
194 return *result; |
|
195 } |
|
196 |
|
197 template<typename ValueType> |
|
198 ValueType any_cast(any & operand) |
|
199 { |
|
200 typedef BOOST_DEDUCED_TYPENAME remove_reference<ValueType>::type nonref; |
|
201 |
|
202 #ifdef BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION |
|
203 // The comment in the above version of 'any_cast' explains when this |
|
204 // assert is fired and what to do. |
|
205 BOOST_STATIC_ASSERT(!is_reference<nonref>::value); |
|
206 #endif |
|
207 |
|
208 nonref * result = any_cast<nonref>(&operand); |
|
209 if(!result) |
|
210 boost::throw_exception(bad_any_cast()); |
|
211 return *result; |
|
212 } |
|
213 |
|
214 // Note: The "unsafe" versions of any_cast are not part of the |
|
215 // public interface and may be removed at any time. They are |
|
216 // required where we know what type is stored in the any and can't |
|
217 // use typeid() comparison, e.g., when our types may travel across |
|
218 // different shared libraries. |
|
219 template<typename ValueType> |
|
220 inline ValueType * unsafe_any_cast(any * operand) |
|
221 { |
|
222 return &static_cast<any::holder<ValueType> *>(operand->content)->held; |
|
223 } |
|
224 |
|
225 template<typename ValueType> |
|
226 inline const ValueType * unsafe_any_cast(const any * operand) |
|
227 { |
|
228 return unsafe_any_cast<ValueType>(const_cast<any *>(operand)); |
|
229 } |
|
230 } |
|
231 |
|
232 // Copyright Kevlin Henney, 2000, 2001, 2002. All rights reserved. |
|
233 // |
|
234 // Distributed under the Boost Software License, Version 1.0. (See |
|
235 // accompanying file LICENSE_1_0.txt or copy at |
|
236 // http://www.boost.org/LICENSE_1_0.txt) |
|
237 |
|
238 #endif |