libstdc++
any
Go to the documentation of this file.
1 // <any> -*- C++ -*-
2 
3 // Copyright (C) 2014-2020 Free Software Foundation, Inc.
4 //
5 // This file is part of the GNU ISO C++ Library. This library is free
6 // software; you can redistribute it and/or modify it under the
7 // terms of the GNU General Public License as published by the
8 // Free Software Foundation; either version 3, or (at your option)
9 // any later version.
10 
11 // This library is distributed in the hope that it will be useful,
12 // but WITHOUT ANY WARRANTY; without even the implied warranty of
13 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 // GNU General Public License for more details.
15 
16 // Under Section 7 of GPL version 3, you are granted additional
17 // permissions described in the GCC Runtime Library Exception, version
18 // 3.1, as published by the Free Software Foundation.
19 
20 // You should have received a copy of the GNU General Public License and
21 // a copy of the GCC Runtime Library Exception along with this program;
22 // see the files COPYING3 and COPYING.RUNTIME respectively. If not, see
23 // <http://www.gnu.org/licenses/>.
24 
25 /** @file include/any
26  * This is a Standard C++ Library header.
27  */
28 
29 #ifndef _GLIBCXX_ANY
30 #define _GLIBCXX_ANY 1
31 
32 #pragma GCC system_header
33 
34 #if __cplusplus >= 201703L
35 
36 #include <typeinfo>
37 #include <new>
38 #include <utility>
39 #include <type_traits>
40 
41 namespace std _GLIBCXX_VISIBILITY(default)
42 {
43 _GLIBCXX_BEGIN_NAMESPACE_VERSION
44 
45  /**
46  * @addtogroup utilities
47  * @{
48  */
49 
50  /**
51  * @brief Exception class thrown by a failed @c any_cast
52  * @ingroup exceptions
53  */
54  class bad_any_cast : public bad_cast
55  {
56  public:
57  virtual const char* what() const noexcept { return "bad any_cast"; }
58  };
59 
60  [[gnu::noreturn]] inline void __throw_bad_any_cast()
61  {
62 #if __cpp_exceptions
63  throw bad_any_cast{};
64 #else
65  __builtin_abort();
66 #endif
67  }
68 
69 #define __cpp_lib_any 201606L
70 
71  /**
72  * @brief A type-safe container of any type.
73  *
74  * An @c any object's state is either empty or it stores a contained object
75  * of CopyConstructible type.
76  */
77  class any
78  {
79  // Holds either pointer to a heap object or the contained object itself.
80  union _Storage
81  {
82  constexpr _Storage() : _M_ptr{nullptr} {}
83 
84  // Prevent trivial copies of this type, buffer might hold a non-POD.
85  _Storage(const _Storage&) = delete;
86  _Storage& operator=(const _Storage&) = delete;
87 
88  void* _M_ptr;
89  aligned_storage<sizeof(_M_ptr), alignof(void*)>::type _M_buffer;
90  };
91 
92  template<typename _Tp, typename _Safe = is_nothrow_move_constructible<_Tp>,
93  bool _Fits = (sizeof(_Tp) <= sizeof(_Storage))
94  && (alignof(_Tp) <= alignof(_Storage))>
95  using _Internal = std::integral_constant<bool, _Safe::value && _Fits>;
96 
97  template<typename _Tp>
98  struct _Manager_internal; // uses small-object optimization
99 
100  template<typename _Tp>
101  struct _Manager_external; // creates contained object on the heap
102 
103  template<typename _Tp>
104  using _Manager = conditional_t<_Internal<_Tp>::value,
105  _Manager_internal<_Tp>,
106  _Manager_external<_Tp>>;
107 
108  template<typename _Tp, typename _Decayed = decay_t<_Tp>>
109  using _Decay = enable_if_t<!is_same<_Decayed, any>::value, _Decayed>;
110 
111  /// Emplace with an object created from @p __args as the contained object.
112  template <typename _Tp, typename... _Args,
113  typename _Mgr = _Manager<_Tp>>
114  void __do_emplace(_Args&&... __args)
115  {
116  reset();
117  _Mgr::_S_create(_M_storage, std::forward<_Args>(__args)...);
118  _M_manager = &_Mgr::_S_manage;
119  }
120 
121  /// Emplace with an object created from @p __il and @p __args as
122  /// the contained object.
123  template <typename _Tp, typename _Up, typename... _Args,
124  typename _Mgr = _Manager<_Tp>>
125  void __do_emplace(initializer_list<_Up> __il, _Args&&... __args)
126  {
127  reset();
128  _Mgr::_S_create(_M_storage, __il, std::forward<_Args>(__args)...);
129  _M_manager = &_Mgr::_S_manage;
130  }
131 
132  public:
133  // construct/destruct
134 
135  /// Default constructor, creates an empty object.
136  constexpr any() noexcept : _M_manager(nullptr) { }
137 
138  /// Copy constructor, copies the state of @p __other
139  any(const any& __other)
140  {
141  if (!__other.has_value())
142  _M_manager = nullptr;
143  else
144  {
145  _Arg __arg;
146  __arg._M_any = this;
147  __other._M_manager(_Op_clone, &__other, &__arg);
148  }
149  }
150 
151  /**
152  * @brief Move constructor, transfer the state from @p __other
153  *
154  * @post @c !__other.has_value() (this postcondition is a GNU extension)
155  */
156  any(any&& __other) noexcept
157  {
158  if (!__other.has_value())
159  _M_manager = nullptr;
160  else
161  {
162  _Arg __arg;
163  __arg._M_any = this;
164  __other._M_manager(_Op_xfer, &__other, &__arg);
165  }
166  }
167 
168  template <typename _Res, typename _Tp, typename... _Args>
169  using __any_constructible =
170  enable_if<__and_<is_copy_constructible<_Tp>,
171  is_constructible<_Tp, _Args...>>::value,
172  _Res>;
173 
174  template <typename _Tp, typename... _Args>
175  using __any_constructible_t =
176  typename __any_constructible<bool, _Tp, _Args...>::type;
177 
178  /// Construct with a copy of @p __value as the contained object.
179  template <typename _ValueType, typename _Tp = _Decay<_ValueType>,
180  typename _Mgr = _Manager<_Tp>,
181  __any_constructible_t<_Tp, _ValueType&&> = true,
182  enable_if_t<!__is_in_place_type<_Tp>::value, bool> = true>
183  any(_ValueType&& __value)
184  : _M_manager(&_Mgr::_S_manage)
185  {
186  _Mgr::_S_create(_M_storage, std::forward<_ValueType>(__value));
187  }
188 
189  /// Construct with a copy of @p __value as the contained object.
190  template <typename _ValueType, typename _Tp = _Decay<_ValueType>,
191  typename _Mgr = _Manager<_Tp>,
192  enable_if_t<__and_v<is_copy_constructible<_Tp>,
193  __not_<is_constructible<_Tp, _ValueType&&>>,
194  __not_<__is_in_place_type<_Tp>>>,
195  bool> = false>
196  any(_ValueType&& __value)
197  : _M_manager(&_Mgr::_S_manage)
198  {
199  _Mgr::_S_create(_M_storage, __value);
200  }
201 
202  /// Construct with an object created from @p __args as the contained object.
203  template <typename _ValueType, typename... _Args,
204  typename _Tp = _Decay<_ValueType>,
205  typename _Mgr = _Manager<_Tp>,
206  __any_constructible_t<_Tp, _Args&&...> = false>
207  explicit
208  any(in_place_type_t<_ValueType>, _Args&&... __args)
209  : _M_manager(&_Mgr::_S_manage)
210  {
211  _Mgr::_S_create(_M_storage, std::forward<_Args>(__args)...);
212  }
213 
214  /// Construct with an object created from @p __il and @p __args as
215  /// the contained object.
216  template <typename _ValueType, typename _Up, typename... _Args,
217  typename _Tp = _Decay<_ValueType>,
218  typename _Mgr = _Manager<_Tp>,
219  __any_constructible_t<_Tp, initializer_list<_Up>,
220  _Args&&...> = false>
221  explicit
222  any(in_place_type_t<_ValueType>,
223  initializer_list<_Up> __il, _Args&&... __args)
224  : _M_manager(&_Mgr::_S_manage)
225  {
226  _Mgr::_S_create(_M_storage, __il, std::forward<_Args>(__args)...);
227  }
228 
229  /// Destructor, calls @c reset()
230  ~any() { reset(); }
231 
232  // assignments
233 
234  /// Copy the state of another object.
235  any& operator=(const any& __rhs)
236  {
237  *this = any(__rhs);
238  return *this;
239  }
240 
241  /**
242  * @brief Move assignment operator
243  *
244  * @post @c !__rhs.has_value() (not guaranteed for other implementations)
245  */
246  any& operator=(any&& __rhs) noexcept
247  {
248  if (!__rhs.has_value())
249  reset();
250  else if (this != &__rhs)
251  {
252  reset();
253  _Arg __arg;
254  __arg._M_any = this;
255  __rhs._M_manager(_Op_xfer, &__rhs, &__arg);
256  }
257  return *this;
258  }
259 
260  /// Store a copy of @p __rhs as the contained object.
261  template<typename _ValueType>
262  enable_if_t<is_copy_constructible<_Decay<_ValueType>>::value, any&>
263  operator=(_ValueType&& __rhs)
264  {
265  *this = any(std::forward<_ValueType>(__rhs));
266  return *this;
267  }
268 
269  /// Emplace with an object created from @p __args as the contained object.
270  template <typename _ValueType, typename... _Args>
271  typename __any_constructible<_Decay<_ValueType>&,
272  _Decay<_ValueType>, _Args&&...>::type
273  emplace(_Args&&... __args)
274  {
275  __do_emplace<_Decay<_ValueType>>(std::forward<_Args>(__args)...);
276  any::_Arg __arg;
277  this->_M_manager(any::_Op_access, this, &__arg);
278  return *static_cast<_Decay<_ValueType>*>(__arg._M_obj);
279  }
280 
281  /// Emplace with an object created from @p __il and @p __args as
282  /// the contained object.
283  template <typename _ValueType, typename _Up, typename... _Args>
284  typename __any_constructible<_Decay<_ValueType>&,
285  _Decay<_ValueType>,
286  initializer_list<_Up>,
287  _Args&&...>::type
288  emplace(initializer_list<_Up> __il, _Args&&... __args)
289  {
290  __do_emplace<_Decay<_ValueType>, _Up>(__il,
291  std::forward<_Args>(__args)...);
292  any::_Arg __arg;
293  this->_M_manager(any::_Op_access, this, &__arg);
294  return *static_cast<_Decay<_ValueType>*>(__arg._M_obj);
295  }
296 
297  // modifiers
298 
299  /// If not empty, destroy the contained object.
300  void reset() noexcept
301  {
302  if (has_value())
303  {
304  _M_manager(_Op_destroy, this, nullptr);
305  _M_manager = nullptr;
306  }
307  }
308 
309  /// Exchange state with another object.
310  void swap(any& __rhs) noexcept
311  {
312  if (!has_value() && !__rhs.has_value())
313  return;
314 
315  if (has_value() && __rhs.has_value())
316  {
317  if (this == &__rhs)
318  return;
319 
320  any __tmp;
321  _Arg __arg;
322  __arg._M_any = &__tmp;
323  __rhs._M_manager(_Op_xfer, &__rhs, &__arg);
324  __arg._M_any = &__rhs;
325  _M_manager(_Op_xfer, this, &__arg);
326  __arg._M_any = this;
327  __tmp._M_manager(_Op_xfer, &__tmp, &__arg);
328  }
329  else
330  {
331  any* __empty = !has_value() ? this : &__rhs;
332  any* __full = !has_value() ? &__rhs : this;
333  _Arg __arg;
334  __arg._M_any = __empty;
335  __full->_M_manager(_Op_xfer, __full, &__arg);
336  }
337  }
338 
339  // observers
340 
341  /// Reports whether there is a contained object or not.
342  bool has_value() const noexcept { return _M_manager != nullptr; }
343 
344 #if __cpp_rtti
345  /// The @c typeid of the contained object, or @c typeid(void) if empty.
346  const type_info& type() const noexcept
347  {
348  if (!has_value())
349  return typeid(void);
350  _Arg __arg;
351  _M_manager(_Op_get_type_info, this, &__arg);
352  return *__arg._M_typeinfo;
353  }
354 #endif
355 
356  template<typename _Tp>
357  static constexpr bool __is_valid_cast()
358  { return __or_<is_reference<_Tp>, is_copy_constructible<_Tp>>::value; }
359 
360  private:
361  enum _Op {
362  _Op_access, _Op_get_type_info, _Op_clone, _Op_destroy, _Op_xfer
363  };
364 
365  union _Arg
366  {
367  void* _M_obj;
368  const std::type_info* _M_typeinfo;
369  any* _M_any;
370  };
371 
372  void (*_M_manager)(_Op, const any*, _Arg*);
373  _Storage _M_storage;
374 
375  template<typename _Tp>
376  friend void* __any_caster(const any* __any);
377 
378  // Manage in-place contained object.
379  template<typename _Tp>
380  struct _Manager_internal
381  {
382  static void
383  _S_manage(_Op __which, const any* __anyp, _Arg* __arg);
384 
385  template<typename _Up>
386  static void
387  _S_create(_Storage& __storage, _Up&& __value)
388  {
389  void* __addr = &__storage._M_buffer;
390  ::new (__addr) _Tp(std::forward<_Up>(__value));
391  }
392 
393  template<typename... _Args>
394  static void
395  _S_create(_Storage& __storage, _Args&&... __args)
396  {
397  void* __addr = &__storage._M_buffer;
398  ::new (__addr) _Tp(std::forward<_Args>(__args)...);
399  }
400  };
401 
402  // Manage external contained object.
403  template<typename _Tp>
404  struct _Manager_external
405  {
406  static void
407  _S_manage(_Op __which, const any* __anyp, _Arg* __arg);
408 
409  template<typename _Up>
410  static void
411  _S_create(_Storage& __storage, _Up&& __value)
412  {
413  __storage._M_ptr = new _Tp(std::forward<_Up>(__value));
414  }
415  template<typename... _Args>
416  static void
417  _S_create(_Storage& __storage, _Args&&... __args)
418  {
419  __storage._M_ptr = new _Tp(std::forward<_Args>(__args)...);
420  }
421  };
422  };
423 
424  /// Exchange the states of two @c any objects.
425  inline void swap(any& __x, any& __y) noexcept { __x.swap(__y); }
426 
427  /// Create an any holding a @c _Tp constructed from @c __args.
428  template <typename _Tp, typename... _Args>
429  any make_any(_Args&&... __args)
430  {
431  return any(in_place_type<_Tp>, std::forward<_Args>(__args)...);
432  }
433 
434  /// Create an any holding a @c _Tp constructed from @c __il and @c __args.
435  template <typename _Tp, typename _Up, typename... _Args>
436  any make_any(initializer_list<_Up> __il, _Args&&... __args)
437  {
438  return any(in_place_type<_Tp>, __il, std::forward<_Args>(__args)...);
439  }
440 
441  /**
442  * @brief Access the contained object.
443  *
444  * @tparam _ValueType A const-reference or CopyConstructible type.
445  * @param __any The object to access.
446  * @return The contained object.
447  * @throw bad_any_cast If <code>
448  * __any.type() != typeid(remove_reference_t<_ValueType>)
449  * </code>
450  */
451  template<typename _ValueType>
452  inline _ValueType any_cast(const any& __any)
453  {
454  using _Up = __remove_cvref_t<_ValueType>;
455  static_assert(any::__is_valid_cast<_ValueType>(),
456  "Template argument must be a reference or CopyConstructible type");
457  static_assert(is_constructible_v<_ValueType, const _Up&>,
458  "Template argument must be constructible from a const value.");
459  auto __p = any_cast<_Up>(&__any);
460  if (__p)
461  return static_cast<_ValueType>(*__p);
462  __throw_bad_any_cast();
463  }
464 
465  /**
466  * @brief Access the contained object.
467  *
468  * @tparam _ValueType A reference or CopyConstructible type.
469  * @param __any The object to access.
470  * @return The contained object.
471  * @throw bad_any_cast If <code>
472  * __any.type() != typeid(remove_reference_t<_ValueType>)
473  * </code>
474  *
475  * @{
476  */
477  template<typename _ValueType>
478  inline _ValueType any_cast(any& __any)
479  {
480  using _Up = __remove_cvref_t<_ValueType>;
481  static_assert(any::__is_valid_cast<_ValueType>(),
482  "Template argument must be a reference or CopyConstructible type");
483  static_assert(is_constructible_v<_ValueType, _Up&>,
484  "Template argument must be constructible from an lvalue.");
485  auto __p = any_cast<_Up>(&__any);
486  if (__p)
487  return static_cast<_ValueType>(*__p);
488  __throw_bad_any_cast();
489  }
490 
491  template<typename _ValueType>
492  inline _ValueType any_cast(any&& __any)
493  {
494  using _Up = __remove_cvref_t<_ValueType>;
495  static_assert(any::__is_valid_cast<_ValueType>(),
496  "Template argument must be a reference or CopyConstructible type");
497  static_assert(is_constructible_v<_ValueType, _Up>,
498  "Template argument must be constructible from an rvalue.");
499  auto __p = any_cast<_Up>(&__any);
500  if (__p)
501  return static_cast<_ValueType>(std::move(*__p));
502  __throw_bad_any_cast();
503  }
504  // @}
505 
506  /// @cond undocumented
507  template<typename _Tp>
508  void* __any_caster(const any* __any)
509  {
510  // any_cast<T> returns non-null if __any->type() == typeid(T) and
511  // typeid(T) ignores cv-qualifiers so remove them:
512  using _Up = remove_cv_t<_Tp>;
513  // The contained value has a decayed type, so if decay_t<U> is not U,
514  // then it's not possible to have a contained value of type U:
515  if constexpr (!is_same_v<decay_t<_Up>, _Up>)
516  return nullptr;
517  // Only copy constructible types can be used for contained values:
518  else if constexpr (!is_copy_constructible_v<_Up>)
519  return nullptr;
520  // First try comparing function addresses, which works without RTTI
521  else if (__any->_M_manager == &any::_Manager<_Up>::_S_manage
522 #if __cpp_rtti
523  || __any->type() == typeid(_Tp)
524 #endif
525  )
526  {
527  any::_Arg __arg;
528  __any->_M_manager(any::_Op_access, __any, &__arg);
529  return __arg._M_obj;
530  }
531  return nullptr;
532  }
533  /// @endcond
534 
535  /**
536  * @brief Access the contained object.
537  *
538  * @tparam _ValueType The type of the contained object.
539  * @param __any A pointer to the object to access.
540  * @return The address of the contained object if <code>
541  * __any != nullptr && __any.type() == typeid(_ValueType)
542  * </code>, otherwise a null pointer.
543  *
544  * @{
545  */
546  template<typename _ValueType>
547  inline const _ValueType* any_cast(const any* __any) noexcept
548  {
549  if constexpr (is_object_v<_ValueType>)
550  if (__any)
551  return static_cast<_ValueType*>(__any_caster<_ValueType>(__any));
552  return nullptr;
553  }
554 
555  template<typename _ValueType>
556  inline _ValueType* any_cast(any* __any) noexcept
557  {
558  if constexpr (is_object_v<_ValueType>)
559  if (__any)
560  return static_cast<_ValueType*>(__any_caster<_ValueType>(__any));
561  return nullptr;
562  }
563  // @}
564 
565  template<typename _Tp>
566  void
567  any::_Manager_internal<_Tp>::
568  _S_manage(_Op __which, const any* __any, _Arg* __arg)
569  {
570  // The contained object is in _M_storage._M_buffer
571  auto __ptr = reinterpret_cast<const _Tp*>(&__any->_M_storage._M_buffer);
572  switch (__which)
573  {
574  case _Op_access:
575  __arg->_M_obj = const_cast<_Tp*>(__ptr);
576  break;
577  case _Op_get_type_info:
578 #if __cpp_rtti
579  __arg->_M_typeinfo = &typeid(_Tp);
580 #endif
581  break;
582  case _Op_clone:
583  ::new(&__arg->_M_any->_M_storage._M_buffer) _Tp(*__ptr);
584  __arg->_M_any->_M_manager = __any->_M_manager;
585  break;
586  case _Op_destroy:
587  __ptr->~_Tp();
588  break;
589  case _Op_xfer:
590  ::new(&__arg->_M_any->_M_storage._M_buffer) _Tp
591  (std::move(*const_cast<_Tp*>(__ptr)));
592  __ptr->~_Tp();
593  __arg->_M_any->_M_manager = __any->_M_manager;
594  const_cast<any*>(__any)->_M_manager = nullptr;
595  break;
596  }
597  }
598 
599  template<typename _Tp>
600  void
601  any::_Manager_external<_Tp>::
602  _S_manage(_Op __which, const any* __any, _Arg* __arg)
603  {
604  // The contained object is *_M_storage._M_ptr
605  auto __ptr = static_cast<const _Tp*>(__any->_M_storage._M_ptr);
606  switch (__which)
607  {
608  case _Op_access:
609  __arg->_M_obj = const_cast<_Tp*>(__ptr);
610  break;
611  case _Op_get_type_info:
612 #if __cpp_rtti
613  __arg->_M_typeinfo = &typeid(_Tp);
614 #endif
615  break;
616  case _Op_clone:
617  __arg->_M_any->_M_storage._M_ptr = new _Tp(*__ptr);
618  __arg->_M_any->_M_manager = __any->_M_manager;
619  break;
620  case _Op_destroy:
621  delete __ptr;
622  break;
623  case _Op_xfer:
624  __arg->_M_any->_M_storage._M_ptr = __any->_M_storage._M_ptr;
625  __arg->_M_any->_M_manager = __any->_M_manager;
626  const_cast<any*>(__any)->_M_manager = nullptr;
627  break;
628  }
629  }
630 
631  /// @}
632 
633  namespace __detail::__variant
634  {
635  template<typename> struct _Never_valueless_alt; // see <variant>
636 
637  // Provide the strong exception-safety guarantee when emplacing an
638  // any into a variant.
639  template<>
640  struct _Never_valueless_alt<std::any>
641  : std::true_type
642  { };
643  } // namespace __detail::__variant
644 
645 _GLIBCXX_END_NAMESPACE_VERSION
646 } // namespace std
647 
648 #endif // C++17
649 #endif // _GLIBCXX_ANY