Lunchbox  1.11.0
 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 
35 // Don't reorder below!
36 #include <boost/serialization/singleton.hpp>
37 #include <boost/serialization/extended_type_info.hpp>
38 #include <boost/serialization/access.hpp>
39 #include <boost/serialization/assume_abstract.hpp>
40 #include <boost/serialization/base_object.hpp>
41 #include <boost/serialization/type_info_implementation.hpp>
42 #include <boost/serialization/shared_ptr.hpp>
43 
44 // See boost/python/type_id.hpp
45 // TODO: add BOOST_TYPEID_COMPARE_BY_NAME to config.hpp
46 # if (defined(__GNUC__) && __GNUC__ >= 3) \
47  || defined(_AIX) \
48  || ( defined(__sgi) && defined(__host_mips)) \
49  || (defined(__hpux) && defined(__HP_aCC)) \
50  || (defined(linux) && defined(__INTEL_COMPILER) && defined(__ICC))
51 # define BOOST_AUX_ANY_TYPE_ID_NAME
52 # include <cstring>
53 # endif
54 
55 
56 namespace lunchbox
57 {
58 
67 class Any
68 {
69 public:
73  LUNCHBOX_API Any();
74 
76  template< typename ValueType >
77  Any( const ValueType& value )
78  : content( new holder< ValueType >( value ))
79  {
80  }
81 
83  LUNCHBOX_API Any( const Any& other );
84 
86  LUNCHBOX_API ~Any();
88 
92  LUNCHBOX_API Any& swap( Any& rhs );
93 
95  template< typename ValueType >
96  Any& operator=( const ValueType& rhs )
97  {
98  Any( rhs ).swap( *this );
99  return *this;
100  }
101 
103  LUNCHBOX_API Any& operator=( Any rhs );
105 
109  LUNCHBOX_API bool empty() const;
110 
116  LUNCHBOX_API const std::type_info& type() const;
117 
122  LUNCHBOX_API bool operator == ( const Any& rhs ) const;
123 
128  bool operator != ( const Any& rhs ) const { return !(*this == rhs); }
130 
131 
133  class placeholder
134  {
135  public:
136  virtual ~placeholder() {}
137 
138  virtual bool operator == ( const placeholder& rhs ) const = 0;
139 
140  bool operator != ( const placeholder& rhs ) const
141  { return !(*this == rhs); }
142 
143  virtual const std::type_info& type() const = 0;
144 
145  virtual placeholder* clone() const = 0;
146 
147  private:
148  friend class boost::serialization::access;
149  template< class Archive >
150  void serialize( Archive&, const unsigned int ) {}
151  };
152 
153  BOOST_SERIALIZATION_ASSUME_ABSTRACT(placeholder)
154 
155  template< typename ValueType >
156  class holder : public placeholder
157  {
158  public:
159  holder()
160  : held()
161  {
162  }
163 
164  explicit holder( const ValueType& value )
165  : held( value )
166  {
167  }
168 
169  virtual const std::type_info& type() const
170  {
171  return typeid(ValueType);
172  }
173 
174  virtual bool operator == ( const placeholder& rhs ) const
175  {
176  return held == static_cast< const holder& >( rhs ).held;
177  }
178 
179  virtual placeholder* clone() const
180  {
181  return new holder( held );
182  }
183 
184  ValueType held;
185 
186  private:
187  holder& operator=( const holder& );
188 
189  friend class boost::serialization::access;
190  template< class Archive >
191  void serialize( Archive & ar, const unsigned int /*version*/ )
192  {
193  // serialize base class information
194  ar & boost::serialization::base_object< placeholder >( *this );
195  ar & held;
196  }
197  };
200 private:
201  template< typename ValueType >
202  friend ValueType* any_cast( Any* );
203 
204  template< typename ValueType >
205  friend ValueType* unsafe_any_cast( Any* );
206 
207  friend class boost::serialization::access;
208  template< class Archive >
209  void serialize( Archive & ar, const unsigned int /*version*/ )
210  {
211  ar & content;
212  }
213 
214  boost::shared_ptr< placeholder > content;
215 };
216 
218 class bad_any_cast : public std::bad_cast
219 {
220 public:
221  LUNCHBOX_API bad_any_cast( const std::string& from, const std::string& to );
222 
223  virtual const char* what() const throw() { return data; }
224 
225 private:
226  char data[256];
227 };
228 
235 template< typename ValueType >
236 ValueType* any_cast( Any* operand )
237 {
238  return operand &&
239 #ifdef BOOST_AUX_ANY_TYPE_ID_NAME
240  std::strcmp(operand->type().name(), typeid(ValueType).name()) == 0
241 #else
242  operand->type() == typeid(ValueType)
243 #endif
244  ? &static_cast<Any::holder<ValueType> *>(operand->content.get())->held
245  : 0;
246 }
247 
254 template< typename ValueType >
255 inline const ValueType* any_cast( const Any* operand )
256 {
257  return any_cast<ValueType>(const_cast<Any *>(operand));
258 }
259 
267 template< typename ValueType >
268 ValueType any_cast( Any& operand )
269 {
270  typedef typename boost::remove_reference< ValueType >::type nonref;
271 
272  nonref* result = any_cast< nonref >( &operand );
273  if( !result )
274  boost::throw_exception(
275  bad_any_cast( demangleTypeID( operand.type().name( )),
276  demangleTypeID( typeid( nonref ).name( ))));
277  return *result;
278 }
279 
287 template< typename ValueType >
288 inline ValueType any_cast( const Any& operand )
289 {
290  typedef typename boost::remove_reference< ValueType >::type nonref;
291 
292  return any_cast< const nonref& >( const_cast< Any& >( operand ));
293 }
294 
301 template< typename ValueType >
302 inline ValueType* unsafe_any_cast( Any* operand )
303 {
304  return &static_cast< Any::holder< ValueType >* >(
305  operand->content.get( ))->held;
306 }
307 
314 template< typename ValueType >
315 inline const ValueType* unsafe_any_cast( const Any* operand )
316 {
317  return unsafe_any_cast< ValueType >( const_cast< Any* > ( operand ));
318 }
319 
326 template< typename ValueType >
327 ValueType unsafe_any_cast( Any& operand )
328 {
329  typedef typename boost::remove_reference< ValueType >::type nonref;
330  return *unsafe_any_cast< nonref >( &operand );
331 }
332 
339 template< typename ValueType >
340 ValueType unsafe_any_cast( const Any& operand )
341 {
342  typedef typename boost::remove_reference< ValueType >::type nonref;
343  return unsafe_any_cast< const nonref& >( const_cast< Any& >( operand ));
344 }
345 
346 }
347 
348 #endif
Defines export visibility macros for Lunchbox.
Any & operator=(const ValueType &rhs)
Assign a new value to this Any.
Definition: any.h:96
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:302
Any(const ValueType &value)
Construct a new Any with the given value.
Definition: any.h:77
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:218
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:236
bool operator!=(const Any &rhs) const
Definition: any.h:128
A class which can hold instances of any type.
Definition: any.h:67
ValueType * unsafe_any_cast(Any *operand)
Retrieve the value stored in an Any without type checking.
Definition: any.h:302
ValueType * any_cast(Any *operand)
Retrieve the value stored in an Any including type checking.
Definition: any.h:236
LUNCHBOX_API bool operator==(const Any &rhs) const