Lunchbox  1.9.1
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
any.h
1 
2 /* Copyright (c) 2012, Daniel Nachbaur <daniel.nachbaur@gmail.com>
3  *
4  * This library is free software; you can redistribute it and/or modify it under
5  * the terms of the GNU Lesser General Public License version 3.0 as published
6  * by the Free Software Foundation.
7  *
8  * This library is distributed in the hope that it will be useful, but WITHOUT
9  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
10  * FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
11  * details.
12  *
13  * You should have received a copy of the GNU Lesser General Public License
14  * along with this library; if not, write to the Free Software Foundation, Inc.,
15  * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
16  */
17 
18 // Based on boost/any.hpp
19 // Copyright Kevlin Henney, 2000, 2001, 2002. All rights reserved.
20 //
21 // Distributed under the Boost Software License, Version 1.0. (See
22 // accompanying file LICENSE_1_0.txt or copy at
23 // http://www.boost.org/LICENSE_1_0.txt)
24 
25 
26 #ifndef LUNCHBOX_ANY_H
27 #define LUNCHBOX_ANY_H
28 
29 #include <lunchbox/api.h>
30 #include <lunchbox/debug.h>
31 
32 #include <boost/type_traits/remove_reference.hpp>
33 #include <boost/shared_ptr.hpp>
34 #include <boost/serialization/access.hpp>
35 #include <boost/serialization/assume_abstract.hpp>
36 #include <boost/serialization/base_object.hpp>
37 #include <boost/serialization/shared_ptr.hpp>
38 
39 // See boost/python/type_id.hpp
40 // TODO: add BOOST_TYPEID_COMPARE_BY_NAME to config.hpp
41 # if (defined(__GNUC__) && __GNUC__ >= 3) \
42  || defined(_AIX) \
43  || ( defined(__sgi) && defined(__host_mips)) \
44  || (defined(__hpux) && defined(__HP_aCC)) \
45  || (defined(linux) && defined(__INTEL_COMPILER) && defined(__ICC))
46 # define BOOST_AUX_ANY_TYPE_ID_NAME
47 # include <cstring>
48 # endif
49 
50 
51 namespace lunchbox
52 {
53 
62 class Any
63 {
64 public:
68  LUNCHBOX_API Any();
69 
71  template< typename ValueType >
72  Any( const ValueType& value )
73  : content( new holder< ValueType >( value ))
74  {
75  }
76 
78  LUNCHBOX_API Any( const Any& other );
79 
81  LUNCHBOX_API ~Any();
83 
87  LUNCHBOX_API Any& swap( Any& rhs );
88 
90  template< typename ValueType >
91  Any& operator=( const ValueType& rhs )
92  {
93  Any( rhs ).swap( *this );
94  return *this;
95  }
96 
98  LUNCHBOX_API Any& operator=( Any rhs );
100 
104  LUNCHBOX_API bool empty() const;
105 
111  LUNCHBOX_API const std::type_info& type() const;
112 
117  LUNCHBOX_API bool operator == ( const Any& rhs ) const;
118 
123  bool operator != ( const Any& rhs ) const { return !(*this == rhs); }
125 
126 
128  class placeholder
129  {
130  public:
131  virtual ~placeholder() {}
132 
133  virtual bool operator == ( const placeholder& rhs ) const = 0;
134 
135  bool operator != ( const placeholder& rhs ) const
136  { return !(*this == rhs); }
137 
138  virtual const std::type_info& type() const = 0;
139 
140  virtual placeholder* clone() const = 0;
141 
142  private:
143  friend class boost::serialization::access;
144  template< class Archive >
145  void serialize( Archive&, const unsigned int ) {}
146  };
147 
148  BOOST_SERIALIZATION_ASSUME_ABSTRACT(placeholder)
149 
150  template< typename ValueType >
151  class holder : public placeholder
152  {
153  public:
154  holder()
155  : held()
156  {
157  }
158 
159  explicit holder( const ValueType& value )
160  : held( value )
161  {
162  }
163 
164  virtual const std::type_info& type() const
165  {
166  return typeid(ValueType);
167  }
168 
169  virtual bool operator == ( const placeholder& rhs ) const
170  {
171  return held == static_cast< const holder& >( rhs ).held;
172  }
173 
174  virtual placeholder* clone() const
175  {
176  return new holder( held );
177  }
178 
179  ValueType held;
180 
181  private:
182  holder& operator=( const holder& );
183 
184  friend class boost::serialization::access;
185  template< class Archive >
186  void serialize( Archive & ar, const unsigned int /*version*/ )
187  {
188  // serialize base class information
189  ar & boost::serialization::base_object< placeholder >( *this );
190  ar & held;
191  }
192  };
195 private:
196  template< typename ValueType >
197  friend ValueType* any_cast( Any* );
198 
199  template< typename ValueType >
200  friend ValueType* unsafe_any_cast( Any* );
201 
202  friend class boost::serialization::access;
203  template< class Archive >
204  void serialize( Archive & ar, const unsigned int /*version*/ )
205  {
206  ar & content;
207  }
208 
209  boost::shared_ptr< placeholder > content;
210 };
211 
213 class bad_any_cast : public std::bad_cast
214 {
215 public:
216  LUNCHBOX_API bad_any_cast( const std::string& from, const std::string& to );
217 
218  virtual const char* what() const throw() { return data; }
219 
220 private:
221  char data[256];
222 };
223 
230 template< typename ValueType >
231 ValueType* any_cast( Any* operand )
232 {
233  return operand &&
234 #ifdef BOOST_AUX_ANY_TYPE_ID_NAME
235  std::strcmp(operand->type().name(), typeid(ValueType).name()) == 0
236 #else
237  operand->type() == typeid(ValueType)
238 #endif
239  ? &static_cast<Any::holder<ValueType> *>(operand->content.get())->held
240  : 0;
241 }
242 
249 template< typename ValueType >
250 inline const ValueType* any_cast( const Any* operand )
251 {
252  return any_cast<ValueType>(const_cast<Any *>(operand));
253 }
254 
262 template< typename ValueType >
263 ValueType any_cast( Any& operand )
264 {
265  typedef typename boost::remove_reference< ValueType >::type nonref;
266 
267  nonref* result = any_cast< nonref >( &operand );
268  if( !result )
269  boost::throw_exception(
270  bad_any_cast( demangleTypeID( operand.type().name( )),
271  demangleTypeID( typeid( nonref ).name( ))));
272  return *result;
273 }
274 
282 template< typename ValueType >
283 inline ValueType any_cast( const Any& operand )
284 {
285  typedef typename boost::remove_reference< ValueType >::type nonref;
286 
287  return any_cast< const nonref& >( const_cast< Any& >( operand ));
288 }
289 
296 template< typename ValueType >
297 inline ValueType* unsafe_any_cast( Any* operand )
298 {
299  return &static_cast< Any::holder< ValueType >* >(
300  operand->content.get( ))->held;
301 }
302 
309 template< typename ValueType >
310 inline const ValueType* unsafe_any_cast( const Any* operand )
311 {
312  return unsafe_any_cast< ValueType >( const_cast< Any* > ( operand ));
313 }
314 
321 template< typename ValueType >
322 ValueType unsafe_any_cast( Any& operand )
323 {
324  typedef typename boost::remove_reference< ValueType >::type nonref;
325  return *unsafe_any_cast< nonref >( &operand );
326 }
327 
334 template< typename ValueType >
335 ValueType unsafe_any_cast( const Any& operand )
336 {
337  typedef typename boost::remove_reference< ValueType >::type nonref;
338  return unsafe_any_cast< const nonref& >( const_cast< Any& >( operand ));
339 }
340 
341 }
342 
343 #endif
Defines export visibility macros for Lunchbox.
Any & operator=(const ValueType &rhs)
Assign a new value to this Any.
Definition: any.h:91
LUNCHBOX_API const std::type_info & type() const
friend ValueType * unsafe_any_cast(Any *)
Retrieve the value stored in an Any without type checking.
Definition: any.h:297
Any(const ValueType &value)
Construct a new Any with the given value.
Definition: any.h:72
LUNCHBOX_API bool empty() const
LUNCHBOX_API Any & swap(Any &rhs)
Exchange the content of this and rhs.
A specialization for exceptions thrown by an unsuccessful any_cast.
Definition: any.h:213
LUNCHBOX_API Any()
Construct a new, empty Any.
LUNCHBOX_API ~Any()
Destruct this Any.
friend ValueType * any_cast(Any *)
Retrieve the value stored in an Any including type checking.
Definition: any.h:231
bool operator!=(const Any &rhs) const
Definition: any.h:123
A class which can hold instances of any type.
Definition: any.h:62
ValueType * unsafe_any_cast(Any *operand)
Retrieve the value stored in an Any without type checking.
Definition: any.h:297
ValueType * any_cast(Any *operand)
Retrieve the value stored in an Any including type checking.
Definition: any.h:231
LUNCHBOX_API bool operator==(const Any &rhs) const