any.h
1 // Boost Software License - Version 1.0 - August 17th, 2003
2 //
3 // Permission is hereby granted, free of charge, to any person or organization
4 // obtaining a copy of the software and accompanying documentation covered by
5 // this license (the "Software") to use, reproduce, display, distribute,
6 // execute, and transmit the Software, and to prepare derivative works of the
7 // Software, and to permit third-parties to whom the Software is furnished to
8 // do so, all subject to the following:
9 //
10 // The copyright notices in the Software and this entire statement, including
11 // the above license grant, this restriction and the following disclaimer,
12 // must be included in all copies of the Software, in whole or in part, and
13 // all derivative works of the Software, unless such copies or derivative
14 // works are solely in the form of machine-executable object code generated by
15 // a source language processor.
16 //
17 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
18 // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
19 // FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT
20 // SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE
21 // FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE,
22 // ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
23 // DEALINGS IN THE SOFTWARE.
24 
25 // See http://www.boost.org/libs/any for Documentation.
26 
27 #ifndef MOMEMTA_ANY_INCLUDED
28 #define MOMEMTA_ANY_INCLUDED
29 
30 #if defined(_MSC_VER)
31 # pragma once
32 #endif
33 
34 // what: variant type momemta::any
35 // who: contributed by Kevlin Henney,
36 // with features contributed and bugs found by
37 // Antony Polukhin, Ed Brey, Mark Rodgers,
38 // Peter Dimov, and James Curran
39 // when: July 2001, April 2013 - May 2013
40 
41 // extracted from boost for MoMEMta
42 
43 #include <algorithm>
44 #include <type_traits>
45 #include <typeinfo>
46 
47 namespace momemta
48 {
49  class any
50  {
51  public: // structors
52 
53  any() noexcept
54  : content(0)
55  {
56  }
57 
58  template<typename ValueType>
59  any(const ValueType & value)
60  : content(new holder<
61  typename std::remove_cv<typename std::decay<const ValueType>::type>::type
62  >(value))
63  {
64  }
65 
66  any(const any & other)
67  : content(other.content ? other.content->clone() : 0)
68  {
69  }
70 
71  // Move constructor
72  any(any&& other) noexcept
73  : content(other.content)
74  {
75  other.content = 0;
76  }
77 
78  // Perfect forwarding of ValueType
79  template<typename ValueType>
80  any(ValueType&& value
81  , typename std::enable_if<!std::is_same<any&, ValueType>::value>::type* = 0 // disable if value has type `any&`
82  , typename std::enable_if<!std::is_const<ValueType>::value>::type* = 0) // disable if value has type `const ValueType&&`
83  : content(new holder< typename std::decay<ValueType>::type >(static_cast<ValueType&&>(value)))
84  {
85  }
86 
87  ~any() noexcept
88  {
89  delete content;
90  }
91 
92  public: // modifiers
93 
94  any & swap(any & rhs) noexcept
95  {
96  std::swap(content, rhs.content);
97  return *this;
98  }
99 
100 
101  any & operator=(const any& rhs)
102  {
103  any(rhs).swap(*this);
104  return *this;
105  }
106 
107  // move assignement
108  any & operator=(any&& rhs) noexcept
109  {
110  rhs.swap(*this);
111  any().swap(rhs);
112  return *this;
113  }
114 
115  // Perfect forwarding of ValueType
116  template <class ValueType>
117  any & operator=(ValueType&& rhs)
118  {
119  any(static_cast<ValueType&&>(rhs)).swap(*this);
120  return *this;
121  }
122 
123  public: // queries
124 
125  bool empty() const noexcept
126  {
127  return !content;
128  }
129 
130  void clear() noexcept
131  {
132  any().swap(*this);
133  }
134 
135  const std::type_info& type() const noexcept
136  {
137  return content ? content->type() : typeid(void);
138  }
139 
140  private: // types
141 
142  class placeholder
143  {
144  public: // structors
145 
146  virtual ~placeholder()
147  {
148  }
149 
150  public: // queries
151 
152  virtual const std::type_info& type() const noexcept = 0;
153 
154  virtual placeholder * clone() const = 0;
155 
156  };
157 
158  template<typename ValueType>
159  class holder : public placeholder
160  {
161  public: // structors
162 
163  holder(const ValueType & value)
164  : held(value)
165  {
166  }
167 
168  holder(ValueType&& value)
169  : held(static_cast< ValueType&& >(value))
170  {
171  }
172  public: // queries
173 
174  virtual const std::type_info& type() const noexcept
175  {
176  return typeid(ValueType);
177  }
178 
179  virtual placeholder * clone() const
180  {
181  return new holder(held);
182  }
183 
184  public: // representation
185 
186  ValueType held;
187 
188  private: // intentionally left unimplemented
189  holder & operator=(const holder &);
190  };
191 
192  private: // representation
193 
194  template<typename ValueType>
195  friend ValueType * any_cast(any *) noexcept;
196 
197  template<typename ValueType>
198  friend ValueType * unsafe_any_cast(any *) noexcept;
199 
200  placeholder * content;
201 
202  };
203 
204  inline void swap(any & lhs, any & rhs) noexcept
205  {
206  lhs.swap(rhs);
207  }
208 
209  class __attribute__((__visibility__("default"))) bad_any_cast :
210  public std::bad_cast
211  {
212  public:
213  virtual const char * what() const noexcept
214  {
215  return "momemta::bad_any_cast: "
216  "failed conversion using momemta::any_cast";
217  }
218  };
219 
220  template<typename ValueType>
221  ValueType * any_cast(any * operand) noexcept
222  {
223  return operand && operand->type() == typeid(ValueType)
224  ? &static_cast<any::holder<typename std::remove_cv<ValueType>::type> *>(operand->content)->held
225  : 0;
226  }
227 
228  template<typename ValueType>
229  inline const ValueType * any_cast(const any * operand) noexcept
230  {
231  return any_cast<ValueType>(const_cast<any *>(operand));
232  }
233 
234  template<typename ValueType>
235  ValueType any_cast(any & operand)
236  {
237  typedef typename std::remove_reference<ValueType>::type nonref;
238 
239 
240  nonref * result = any_cast<nonref>(&operand);
241  if(!result)
242  throw bad_any_cast();
243 
244  // Attempt to avoid construction of a temporary object in cases when
245  // `ValueType` is not a reference. Example:
246  // `static_cast<std::string>(*result);`
247  // which is equal to `std::string(*result);`
248  typedef typename std::conditional<
249  std::is_reference<ValueType>::value,
250  ValueType,
251  typename std::add_lvalue_reference<ValueType>::type
252  >::type ref_type;
253 
254  return static_cast<ref_type>(*result);
255  }
256 
257  template<typename ValueType>
258  inline ValueType any_cast(const any & operand)
259  {
260  typedef typename std::remove_reference<ValueType>::type nonref;
261  return any_cast<const nonref &>(const_cast<any &>(operand));
262  }
263 
264  template<typename ValueType>
265  inline ValueType any_cast(any&& operand)
266  {
267  static_assert(
268  std::is_rvalue_reference<ValueType&&>::value /*true if ValueType is rvalue or just a value*/
269  || std::is_const< typename std::remove_reference<ValueType>::type >::value,
270  "momemta::any_cast shall not be used for getting nonconst references to temporary objects"
271  );
272  return any_cast<ValueType>(operand);
273  }
274 
275 
276  // Note: The "unsafe" versions of any_cast are not part of the
277  // public interface and may be removed at any time. They are
278  // required where we know what type is stored in the any and can't
279  // use typeid() comparison, e.g., when our types may travel across
280  // different shared libraries.
281  template<typename ValueType>
282  inline ValueType * unsafe_any_cast(any * operand) noexcept
283  {
284  return &static_cast<any::holder<ValueType> *>(operand->content)->held;
285  }
286 
287  template<typename ValueType>
288  inline const ValueType * unsafe_any_cast(const any * operand) noexcept
289  {
290  return unsafe_any_cast<ValueType>(const_cast<any *>(operand));
291  }
292 }
293 
294 // Copyright Kevlin Henney, 2000, 2001, 2002. All rights reserved.
295 //
296 // Distributed under the Boost Software License, Version 1.0. (See
297 // accompanying file LICENSE_1_0.txt or copy at
298 // http://www.boost.org/LICENSE_1_0.txt)
299 
300 #endif
Definition: Graph.h:21