Lunchbox  1.8.0
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 
61 class Any
62 {
63 public:
67  LUNCHBOX_API Any();
68 
70  template< typename ValueType >
71  Any( const ValueType& value )
72  : content( new holder< ValueType >( value ))
73  {
74  }
75 
77  LUNCHBOX_API Any( const Any& other );
78 
80  LUNCHBOX_API ~Any();
82 
86  LUNCHBOX_API Any& swap( Any& rhs );
87 
89  template< typename ValueType >
90  Any& operator=( const ValueType& rhs )
91  {
92  Any( rhs ).swap( *this );
93  return *this;
94  }
95 
97  LUNCHBOX_API Any& operator=( Any rhs );
99 
103  LUNCHBOX_API bool empty() const;
104 
110  LUNCHBOX_API const std::type_info& type() const;
111 
116  LUNCHBOX_API bool operator == ( const Any& rhs ) const;
117 
122  bool operator != ( const Any& rhs ) const { return !(*this == rhs); }
124 
125 
127  class placeholder
128  {
129  public:
130  virtual ~placeholder() {}
131 
132  virtual bool operator == ( const placeholder& rhs ) const = 0;
133 
134  bool operator != ( const placeholder& rhs ) const
135  { return !(*this == rhs); }
136 
137  virtual const std::type_info& type() const = 0;
138 
139  virtual placeholder* clone() const = 0;
140 
141  private:
142  friend class boost::serialization::access;
143  template< class Archive >
144  void serialize( Archive & ar, const unsigned int version )
145  {
146  }
147  };
148 
149  BOOST_SERIALIZATION_ASSUME_ABSTRACT(placeholder)
150 
151  template< typename ValueType >
152  class holder : public placeholder
153  {
154  public:
155  holder()
156  : held()
157  {
158  }
159 
160  holder( const ValueType& value )
161  : held( value )
162  {
163  }
164 
165  virtual const std::type_info& type() const
166  {
167  return typeid(ValueType);
168  }
169 
170  virtual bool operator == ( const placeholder& rhs ) const
171  {
172  return held == static_cast< const holder& >( rhs ).held;
173  }
174 
175  virtual placeholder* clone() const
176  {
177  return new holder( held );
178  }
179 
180  ValueType held;
181 
182  private:
183  holder& operator=( const holder& );
184 
185  friend class boost::serialization::access;
186  template< class Archive >
187  void serialize( Archive & ar, const unsigned int version )
188  {
189  // serialize base class information
190  ar & boost::serialization::base_object< placeholder >( *this );
191  ar & held;
192  }
193  };
196 private:
197  template< typename ValueType >
198  friend ValueType* any_cast( Any* );
199 
200  template< typename ValueType >
201  friend ValueType* unsafe_any_cast( Any* );
202 
203  friend class boost::serialization::access;
204  template< class Archive >
205  void serialize( Archive & ar, const unsigned int version )
206  {
207  ar & content;
208  }
209 
210  boost::shared_ptr< placeholder > content;
211 };
212 
214 class bad_any_cast : public std::bad_cast
215 {
216 public:
217  LUNCHBOX_API bad_any_cast( const std::string& from, const std::string& to );
218 
219  virtual const char* what() const throw() { return data; }
220 
221 private:
222  char data[256];
223 };
224 
231 template< typename ValueType >
232 ValueType* any_cast( Any* operand )
233 {
234  return operand &&
235 #ifdef BOOST_AUX_ANY_TYPE_ID_NAME
236  std::strcmp(operand->type().name(), typeid(ValueType).name()) == 0
237 #else
238  operand->type() == typeid(ValueType)
239 #endif
240  ? &static_cast<Any::holder<ValueType> *>(operand->content.get())->held
241  : 0;
242 }
243 
250 template< typename ValueType >
251 inline const ValueType* any_cast( const Any* operand )
252 {
253  return any_cast<ValueType>(const_cast<Any *>(operand));
254 }
255 
263 template< typename ValueType >
264 ValueType any_cast( Any& operand )
265 {
266  typedef typename boost::remove_reference< ValueType >::type nonref;
267 
268  nonref* result = any_cast< nonref >( &operand );
269  if( !result )
270  boost::throw_exception(
271  bad_any_cast( demangleTypeID( operand.type().name( )),
272  demangleTypeID( typeid( nonref ).name( ))));
273  return *result;
274 }
275 
283 template< typename ValueType >
284 inline ValueType any_cast( const Any& operand )
285 {
286  typedef typename boost::remove_reference< ValueType >::type nonref;
287 
288  return any_cast< const nonref& >( const_cast< Any& >( operand ));
289 }
290 
297 template< typename ValueType >
298 inline ValueType* unsafe_any_cast( Any* operand )
299 {
300  return &static_cast< Any::holder< ValueType >* >(
301  operand->content.get( ))->held;
302 }
303 
310 template< typename ValueType >
311 inline const ValueType* unsafe_any_cast( const Any* operand )
312 {
313  return unsafe_any_cast< ValueType >( const_cast< Any* > ( operand ));
314 }
315 
322 template< typename ValueType >
323 ValueType unsafe_any_cast( Any& operand )
324 {
325  typedef typename boost::remove_reference< ValueType >::type nonref;
326  return *unsafe_any_cast< nonref >( &operand );
327 }
328 
335 template< typename ValueType >
336 ValueType unsafe_any_cast( const Any& operand )
337 {
338  typedef typename boost::remove_reference< ValueType >::type nonref;
339  return unsafe_any_cast< const nonref& >( const_cast< Any& >( operand ));
340 }
341 
342 }
343 
344 #endif