Lunchbox  1.16.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 #ifndef LUNCHBOX_ANY_H
26 #define LUNCHBOX_ANY_H
27 
28 #include <lunchbox/api.h>
29 #include <lunchbox/debug.h>
30 
31 #include <boost/shared_ptr.hpp>
32 #include <boost/type_traits/remove_reference.hpp>
33 
34 // Don't reorder below!
35 #include <boost/serialization/access.hpp>
36 #include <boost/serialization/assume_abstract.hpp>
37 #include <boost/serialization/base_object.hpp>
38 #include <boost/serialization/extended_type_info.hpp>
39 #include <boost/serialization/shared_ptr.hpp>
40 #include <boost/serialization/singleton.hpp>
41 #include <boost/serialization/type_info_implementation.hpp>
42 
43 // See boost/python/type_id.hpp
44 // TODO: add BOOST_TYPEID_COMPARE_BY_NAME to config.hpp
45 #if (defined(__GNUC__) && __GNUC__ >= 3) || defined(_AIX) || \
46  (defined(__sgi) && defined(__host_mips)) || \
47  (defined(__hpux) && defined(__HP_aCC)) || \
48  (defined(linux) && defined(__INTEL_COMPILER) && defined(__ICC))
49 #define BOOST_AUX_ANY_TYPE_ID_NAME
50 #include <cstring>
51 #endif
52 
53 namespace lunchbox
54 {
63 class Any
64 {
65 public:
69  LUNCHBOX_API Any();
70 
72  // cppcheck-suppress noExplicitConstructor
73  template <typename ValueType>
74  Any(const ValueType& value)
75  : content(new holder<ValueType>(value))
76  {
77  }
78 
80  LUNCHBOX_API Any(const Any& other);
81 
83  LUNCHBOX_API ~Any();
85 
89  LUNCHBOX_API Any& swap(Any& rhs);
90 
92  template <typename ValueType>
93  Any& operator=(const ValueType& rhs)
94  {
95  Any(rhs).swap(*this);
96  return *this;
97  }
98 
100  LUNCHBOX_API Any& operator=(Any rhs);
102 
106  LUNCHBOX_API bool empty() const;
107 
113  LUNCHBOX_API const std::type_info& type() const;
114 
119  LUNCHBOX_API bool operator==(const Any& rhs) const;
120 
125  bool operator!=(const Any& rhs) const { return !(*this == rhs); }
127 
129  class placeholder
130  {
131  public:
132  virtual ~placeholder() {}
133  virtual bool operator==(const placeholder& rhs) const = 0;
134 
135  bool operator!=(const placeholder& rhs) const
136  {
137  return !(*this == rhs);
138  }
139 
140  virtual const std::type_info& type() const = 0;
141 
142  virtual placeholder* clone() const = 0;
143 
144  private:
145  friend class boost::serialization::access;
146  template <class Archive>
147  void serialize(Archive&, const unsigned int)
148  {
149  }
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 { return typeid(ValueType); }
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 { return new holder(held); }
175  ValueType held;
176 
177  private:
178  holder& operator=(const holder&);
179 
180  friend class boost::serialization::access;
181  template <class Archive>
182  void serialize(Archive& ar, const unsigned int /*version*/)
183  {
184  // serialize base class information
185  ar& boost::serialization::base_object<placeholder>(*this);
186  ar& held;
187  }
188  };
191 private:
192  template <typename ValueType>
193  friend ValueType* any_cast(Any*);
194 
195  template <typename ValueType>
196  friend ValueType* unsafe_any_cast(Any*);
197 
198  friend class boost::serialization::access;
199  template <class Archive>
200  void serialize(Archive& ar, const unsigned int /*version*/)
201  {
202  ar& content;
203  }
204 
205  boost::shared_ptr<placeholder> content;
206 };
207 
209 class bad_any_cast : public std::bad_cast
210 {
211 public:
212  LUNCHBOX_API bad_any_cast(const std::string& from, const std::string& to);
213 
214  virtual const char* what() const throw() { return data; }
215 private:
216  char data[256];
217 };
218 
225 template <typename ValueType>
226 ValueType* any_cast(Any* operand)
227 {
228  return operand &&
229 #ifdef BOOST_AUX_ANY_TYPE_ID_NAME
230  std::strcmp(operand->type().name(),
231  typeid(ValueType).name()) == 0
232 #else
233  operand->type() == typeid(ValueType)
234 #endif
235  ? &static_cast<Any::holder<ValueType>*>(operand->content.get())
236  ->held
237  : 0;
238 }
239 
246 template <typename ValueType>
247 inline const ValueType* any_cast(const Any* operand)
248 {
249  return any_cast<ValueType>(const_cast<Any*>(operand));
250 }
251 
259 template <typename ValueType>
260 ValueType any_cast(Any& operand)
261 {
262  typedef typename boost::remove_reference<ValueType>::type nonref;
263 
264  nonref* result = any_cast<nonref>(&operand);
265  if (!result)
266  boost::throw_exception(
267  bad_any_cast(demangleTypeID(operand.type().name()),
268  demangleTypeID(typeid(nonref).name())));
269  return *result;
270 }
271 
279 template <typename ValueType>
280 inline ValueType any_cast(const Any& operand)
281 {
282  typedef typename boost::remove_reference<ValueType>::type nonref;
283 
284  return any_cast<const nonref&>(const_cast<Any&>(operand));
285 }
286 
293 template <typename ValueType>
294 inline ValueType* unsafe_any_cast(Any* operand)
295 {
296  return &static_cast<Any::holder<ValueType>*>(operand->content.get())->held;
297 }
298 
305 template <typename ValueType>
306 inline const ValueType* unsafe_any_cast(const Any* operand)
307 {
308  return unsafe_any_cast<ValueType>(const_cast<Any*>(operand));
309 }
310 
317 template <typename ValueType>
318 ValueType unsafe_any_cast(Any& operand)
319 {
320  typedef typename boost::remove_reference<ValueType>::type nonref;
321  return *unsafe_any_cast<nonref>(&operand);
322 }
323 
330 template <typename ValueType>
331 ValueType unsafe_any_cast(const Any& operand)
332 {
333  typedef typename boost::remove_reference<ValueType>::type nonref;
334  return unsafe_any_cast<const nonref&>(const_cast<Any&>(operand));
335 }
336 }
337 
338 #endif
Defines export visibility macros for library Lunchbox.
Any & operator=(const ValueType &rhs)
Assign a new value to this Any.
Definition: any.h:93
friend ValueType * unsafe_any_cast(Any *)
Retrieve the value stored in an Any without type checking.
Definition: any.h:294
bool empty() const
Any(const ValueType &value)
Construct a new Any with the given value.
Definition: any.h:74
bool operator==(const Any &rhs) const
Any()
Construct a new, empty Any.
A specialization for exceptions thrown by an unsuccessful any_cast.
Definition: any.h:209
Any & swap(Any &rhs)
Exchange the content of this and rhs.
const std::type_info & type() const
friend ValueType * any_cast(Any *)
Retrieve the value stored in an Any including type checking.
Definition: any.h:226
Abstraction layer and common utilities for multi-threaded programming.
Definition: algorithm.h:29
bool operator!=(const Any &rhs) const
Definition: any.h:125
A class which can hold instances of any type.
Definition: any.h:63
~Any()
Destruct this Any.