1// <any> -*- C++ -*-
2
3// Copyright (C) 2014-2018 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
41namespace 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 201603
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_<is_copy_constructible<_Tp>,
193				 __not_<is_constructible<_Tp, _ValueType&&>>,
194			         __not_<__is_in_place_type<_Tp>>>::value,
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_cv_t<remove_reference_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_cv_t<remove_reference_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_cv_t<remove_reference_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  template<typename _Tp>
507    void* __any_caster(const any* __any)
508    {
509      if constexpr (is_copy_constructible_v<decay_t<_Tp>>)
510	{
511	  if (__any->_M_manager == &any::_Manager<decay_t<_Tp>>::_S_manage)
512	    {
513	      any::_Arg __arg;
514	      __any->_M_manager(any::_Op_access, __any, &__arg);
515	      return __arg._M_obj;
516	    }
517	}
518      return nullptr;
519    }
520
521  /**
522   * @brief Access the contained object.
523   *
524   * @tparam  _ValueType  The type of the contained object.
525   * @param   __any       A pointer to the object to access.
526   * @return  The address of the contained object if <code>
527   *          __any != nullptr && __any.type() == typeid(_ValueType)
528   *          </code>, otherwise a null pointer.
529   *
530   * @{
531   */
532  template<typename _ValueType>
533    inline const _ValueType* any_cast(const any* __any) noexcept
534    {
535      if (__any)
536	return static_cast<_ValueType*>(__any_caster<_ValueType>(__any));
537      return nullptr;
538    }
539
540  template<typename _ValueType>
541    inline _ValueType* any_cast(any* __any) noexcept
542    {
543      if (__any)
544	return static_cast<_ValueType*>(__any_caster<_ValueType>(__any));
545      return nullptr;
546    }
547  // @}
548
549  template<typename _Tp>
550    void
551    any::_Manager_internal<_Tp>::
552    _S_manage(_Op __which, const any* __any, _Arg* __arg)
553    {
554      // The contained object is in _M_storage._M_buffer
555      auto __ptr = reinterpret_cast<const _Tp*>(&__any->_M_storage._M_buffer);
556      switch (__which)
557      {
558      case _Op_access:
559	__arg->_M_obj = const_cast<_Tp*>(__ptr);
560	break;
561      case _Op_get_type_info:
562#if __cpp_rtti
563	__arg->_M_typeinfo = &typeid(_Tp);
564#endif
565	break;
566      case _Op_clone:
567	::new(&__arg->_M_any->_M_storage._M_buffer) _Tp(*__ptr);
568	__arg->_M_any->_M_manager = __any->_M_manager;
569	break;
570      case _Op_destroy:
571	__ptr->~_Tp();
572	break;
573      case _Op_xfer:
574	::new(&__arg->_M_any->_M_storage._M_buffer) _Tp
575	  (std::move(*const_cast<_Tp*>(__ptr)));
576	__ptr->~_Tp();
577	__arg->_M_any->_M_manager = __any->_M_manager;
578	const_cast<any*>(__any)->_M_manager = nullptr;
579	break;
580      }
581    }
582
583  template<typename _Tp>
584    void
585    any::_Manager_external<_Tp>::
586    _S_manage(_Op __which, const any* __any, _Arg* __arg)
587    {
588      // The contained object is *_M_storage._M_ptr
589      auto __ptr = static_cast<const _Tp*>(__any->_M_storage._M_ptr);
590      switch (__which)
591      {
592      case _Op_access:
593	__arg->_M_obj = const_cast<_Tp*>(__ptr);
594	break;
595      case _Op_get_type_info:
596#if __cpp_rtti
597	__arg->_M_typeinfo = &typeid(_Tp);
598#endif
599	break;
600      case _Op_clone:
601	__arg->_M_any->_M_storage._M_ptr = new _Tp(*__ptr);
602	__arg->_M_any->_M_manager = __any->_M_manager;
603	break;
604      case _Op_destroy:
605	delete __ptr;
606	break;
607      case _Op_xfer:
608	__arg->_M_any->_M_storage._M_ptr = __any->_M_storage._M_ptr;
609	__arg->_M_any->_M_manager = __any->_M_manager;
610	const_cast<any*>(__any)->_M_manager = nullptr;
611	break;
612      }
613    }
614
615  /// @}
616
617_GLIBCXX_END_NAMESPACE_VERSION
618} // namespace std
619
620#endif // C++14
621
622#endif // _GLIBCXX_ANY
623