Lunchbox  1.12.0
Multi-threaded C++ toolbox library for all application developers creating high-performance multi-threaded programs.
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  // cppcheck-suppress noExplicitConstructor
77  template< typename ValueType > Any( const ValueType& value )
78  : content( new holder< ValueType >( value ))
79  {}
80 
82  LUNCHBOX_API Any( const Any& other );
83 
85  LUNCHBOX_API ~Any();
87 
91  LUNCHBOX_API Any& swap( Any& rhs );
92 
94  template< typename ValueType >
95  Any& operator=( const ValueType& rhs )
96  {
97  Any( rhs ).swap( *this );
98  return *this;
99  }
100 
102  LUNCHBOX_API Any& operator=( Any rhs );
104 
108  LUNCHBOX_API bool empty() const;
109 
115  LUNCHBOX_API const std::type_info& type() const;
116 
121  LUNCHBOX_API bool operator == ( const Any& rhs ) const;
122 
127  bool operator != ( const Any& rhs ) const { return !(*this == rhs); }
129 
130 
132  class placeholder
133  {
134  public:
135  virtual ~placeholder() {}
136 
137  virtual bool operator == ( const placeholder& rhs ) const = 0;
138 
139  bool operator != ( const placeholder& rhs ) const
140  { return !(*this == rhs); }
141 
142  virtual const std::type_info& type() const = 0;
143 
144  virtual placeholder* clone() const = 0;
145 
146  private:
147  friend class boost::serialization::access;
148  template< class Archive >
149  void serialize( Archive&, const unsigned int ) {}
150  };
151 
152  BOOST_SERIALIZATION_ASSUME_ABSTRACT(placeholder)
153 
154  template< typename ValueType >
155  class holder : public placeholder
156  {
157  public:
158  holder()
159  : held()
160  {
161  }
162 
163  explicit holder( const ValueType& value )
164  : held( value )
165  {
166  }
167 
168  virtual const std::type_info& type() const
169  {
170  return typeid(ValueType);
171  }
172 
173  virtual bool operator == ( const placeholder& rhs ) const
174  {
175  return held == static_cast< const holder& >( rhs ).held;
176  }
177 
178  virtual placeholder* clone() const
179  {
180  return new holder( held );
181  }
182 
183  ValueType held;
184 
185  private:
186  holder& operator=( const holder& );
187 
188  friend class boost::serialization::access;
189  template< class Archive >
190  void serialize( Archive & ar, const unsigned int /*version*/ )
191  {
192  // serialize base class information
193  ar & boost::serialization::base_object< placeholder >( *this );
194  ar & held;
195  }
196  };
199 private:
200  template< typename ValueType >
201  friend ValueType* any_cast( Any* );
202 
203  template< typename ValueType >
204  friend ValueType* unsafe_any_cast( Any* );
205 
206  friend class boost::serialization::access;
207  template< class Archive >
208  void serialize( Archive & ar, const unsigned int /*version*/ )
209  {
210  ar & content;
211  }
212 
213  boost::shared_ptr< placeholder > content;
214 };
215 
217 class bad_any_cast : public std::bad_cast
218 {
219 public:
220  LUNCHBOX_API bad_any_cast( const std::string& from, const std::string& to );
221 
222  virtual const char* what() const throw() { return data; }
223 
224 private:
225  char data[256];
226 };
227 
234 template< typename ValueType >
235 ValueType* any_cast( Any* operand )
236 {
237  return operand &&
238 #ifdef BOOST_AUX_ANY_TYPE_ID_NAME
239  std::strcmp(operand->type().name(), typeid(ValueType).name()) == 0
240 #else
241  operand->type() == typeid(ValueType)
242 #endif
243  ? &static_cast<Any::holder<ValueType> *>(operand->content.get())->held
244  : 0;
245 }
246 
253 template< typename ValueType >
254 inline const ValueType* any_cast( const Any* operand )
255 {
256  return any_cast<ValueType>(const_cast<Any *>(operand));
257 }
258 
266 template< typename ValueType >
267 ValueType any_cast( Any& operand )
268 {
269  typedef typename boost::remove_reference< ValueType >::type nonref;
270 
271  nonref* result = any_cast< nonref >( &operand );
272  if( !result )
273  boost::throw_exception(
274  bad_any_cast( demangleTypeID( operand.type().name( )),
275  demangleTypeID( typeid( nonref ).name( ))));
276  return *result;
277 }
278 
286 template< typename ValueType >
287 inline ValueType any_cast( const Any& operand )
288 {
289  typedef typename boost::remove_reference< ValueType >::type nonref;
290 
291  return any_cast< const nonref& >( const_cast< Any& >( operand ));
292 }
293 
300 template< typename ValueType >
301 inline ValueType* unsafe_any_cast( Any* operand )
302 {
303  return &static_cast< Any::holder< ValueType >* >(
304  operand->content.get( ))->held;
305 }
306 
313 template< typename ValueType >
314 inline const ValueType* unsafe_any_cast( const Any* operand )
315 {
316  return unsafe_any_cast< ValueType >( const_cast< Any* > ( operand ));
317 }
318 
325 template< typename ValueType >
326 ValueType unsafe_any_cast( Any& operand )
327 {
328  typedef typename boost::remove_reference< ValueType >::type nonref;
329  return *unsafe_any_cast< nonref >( &operand );
330 }
331 
338 template< typename ValueType >
339 ValueType unsafe_any_cast( const Any& operand )
340 {
341  typedef typename boost::remove_reference< ValueType >::type nonref;
342  return unsafe_any_cast< const nonref& >( const_cast< Any& >( operand ));
343 }
344 
345 }
346 
347 #endif
Defines export visibility macros for library Lunchbox.
Any & operator=(const ValueType &rhs)
Assign a new value to this Any.
Definition: any.h:95
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:301
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:217
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:235
Abstraction layer and common utilities for multi-threaded programming.
Definition: algorithm.h:32
bool operator!=(const Any &rhs) const
Definition: any.h:127
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:301
ValueType * any_cast(Any *operand)
Retrieve the value stored in an Any including type checking.
Definition: any.h:235
LUNCHBOX_API bool operator==(const Any &rhs) const