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