// <experimental/any> -*- C++ -*-

// Copyright (C) 2014-2020 Free Software Foundation, Inc.
//
// This file is part of the GNU ISO C++ Library.  This library is free
// software; you can redistribute it and/or modify it under the
// terms of the GNU General Public License as published by the
// Free Software Foundation; either version 3, or (at your option)
// any later version.

// This library is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
// GNU General Public License for more details.

// Under Section 7 of GPL version 3, you are granted additional
// permissions described in the GCC Runtime Library Exception, version
// 3.1, as published by the Free Software Foundation.

// You should have received a copy of the GNU General Public License and
// a copy of the GCC Runtime Library Exception along with this program;
// see the files COPYING3 and COPYING.RUNTIME respectively.  If not, see
// <http://www.gnu.org/licenses/>.

/** @file experimental/any
 *  This is a TS C++ Library header.
 *  @ingroup libfund-ts
 */

#ifndef _GLIBCXX_EXPERIMENTAL_ANY
#define _GLIBCXX_EXPERIMENTAL_ANY 1

#pragma GCC system_header

#if __cplusplus >= 201402L

#include <typeinfo>
#include <new>
#include <utility>
#include <type_traits>
#include <experimental/bits/lfts_config.h>

namespace std _GLIBCXX_VISIBILITY(default)
{
_GLIBCXX_BEGIN_NAMESPACE_VERSION

namespace experimental
{
inline namespace fundamentals_v1
{
  /**
   * @defgroup any Type-safe container of any type
   * @ingroup libfund-ts
   *
   * A type-safe container for single values of value types, as
   * described in n3804 "Any Library Proposal (Revision 3)".
   *
   * @{
   */

#define __cpp_lib_experimental_any 201411

  /**
   *  @brief Exception class thrown by a failed @c any_cast
   *  @ingroup exceptions
   */
  class bad_any_cast : public bad_cast
  {
  public:
    virtual const char* what() const noexcept { return "bad any_cast"; }
  };

  /// @cond undocumented
  [[gnu::noreturn]] inline void __throw_bad_any_cast()
  {
#if __cpp_exceptions
    throw bad_any_cast{};
#else
    __builtin_abort();
#endif
  }
  /// @endcond

  /**
   *  @brief A type-safe container of any type.
   * 
   *  An @c any object's state is either empty or it stores a contained object
   *  of CopyConstructible type.
   */
  class any
  {
    // Holds either pointer to a heap object or the contained object itself.
    union _Storage
    {
      // This constructor intentionally doesn't initialize anything.
      _Storage() = default;

      // Prevent trivial copies of this type, buffer might hold a non-POD.
      _Storage(const _Storage&) = delete;
      _Storage& operator=(const _Storage&) = delete;

      void* _M_ptr;
      aligned_storage<sizeof(_M_ptr), alignof(void*)>::type _M_buffer;
    };

    template<typename _Tp, typename _Safe = is_nothrow_move_constructible<_Tp>,
	     bool _Fits = (sizeof(_Tp) <= sizeof(_Storage))
			  && (alignof(_Tp) <= alignof(_Storage))>
      using _Internal = std::integral_constant<bool, _Safe::value && _Fits>;

    template<typename _Tp>
      struct _Manager_internal; // uses small-object optimization

    template<typename _Tp>
      struct _Manager_external; // creates contained object on the heap

    template<typename _Tp>
      using _Manager = conditional_t<_Internal<_Tp>::value,
				     _Manager_internal<_Tp>,
				     _Manager_external<_Tp>>;

    template<typename _Tp, typename _Decayed = decay_t<_Tp>>
      using _Decay = enable_if_t<!is_same<_Decayed, any>::value, _Decayed>;

  public:
    // construct/destruct

    /// Default constructor, creates an empty object.
    any() noexcept : _M_manager(nullptr) { }

    /// Copy constructor, copies the state of @p __other
    any(const any& __other)
    {
      if (__other.empty())
	_M_manager = nullptr;
      else
	{
	  _Arg __arg;
	  __arg._M_any = this;
	  __other._M_manager(_Op_clone, &__other, &__arg);
	}
    }

    /**
     * @brief Move constructor, transfer the state from @p __other
     *
     * @post @c __other.empty() (this postcondition is a GNU extension)
     */
    any(any&& __other) noexcept
    {
      if (__other.empty())
	_M_manager = nullptr;
      else
	{
	  _Arg __arg;
	  __arg._M_any = this;
	  __other._M_manager(_Op_xfer, &__other, &__arg);
	}
    }

    /// Construct with a copy of @p __value as the contained object.
    template <typename _ValueType, typename _Tp = _Decay<_ValueType>,
	      typename _Mgr = _Manager<_Tp>,
              typename enable_if<is_constructible<_Tp, _ValueType&&>::value,
                                 bool>::type = true>
      any(_ValueType&& __value)
      : _M_manager(&_Mgr::_S_manage)
      {
        _Mgr::_S_create(_M_storage, std::forward<_ValueType>(__value));
	static_assert(is_copy_constructible<_Tp>::value,
		      "The contained object must be CopyConstructible");
      }

    /// Construct with a copy of @p __value as the contained object.
    template <typename _ValueType, typename _Tp = _Decay<_ValueType>,
	      typename _Mgr = _Manager<_Tp>,
              typename enable_if<!is_constructible<_Tp, _ValueType&&>::value,
                                 bool>::type = false>
      any(_ValueType&& __value)
      : _M_manager(&_Mgr::_S_manage)
      {
        _Mgr::_S_create(_M_storage, __value);
	static_assert(is_copy_constructible<_Tp>::value,
		      "The contained object must be CopyConstructible");
      }

    /// Destructor, calls @c clear()
    ~any() { clear(); }

    // assignments

    /// Copy the state of another object.
    any& operator=(const any& __rhs)
    {
      *this = any(__rhs);
      return *this;
    }

    /**
     * @brief Move assignment operator
     *
     * @post @c __rhs.empty() (not guaranteed for other implementations)
     */
    any& operator=(any&& __rhs) noexcept
    {
      if (__rhs.empty())
	clear();
      else if (this != &__rhs)
	{
	  clear();
	  _Arg __arg;
	  __arg._M_any = this;
	  __rhs._M_manager(_Op_xfer, &__rhs, &__arg);
	}
      return *this;
    }

    /// Store a copy of @p __rhs as the contained object.
    template<typename _ValueType>
      enable_if_t<!is_same<any, decay_t<_ValueType>>::value, any&>
      operator=(_ValueType&& __rhs)
      {
	*this = any(std::forward<_ValueType>(__rhs));
	return *this;
      }

    // modifiers

    /// If not empty, destroy the contained object.
    void clear() noexcept
    {
      if (!empty())
      {
	_M_manager(_Op_destroy, this, nullptr);
	_M_manager = nullptr;
      }
    }

    /// Exchange state with another object.
    void swap(any& __rhs) noexcept
    {
      if (empty() && __rhs.empty())
	return;

      if (!empty() && !__rhs.empty())
	{
	  if (this == &__rhs)
	    return;

	  any __tmp;
	  _Arg __arg;
	  __arg._M_any = &__tmp;
	  __rhs._M_manager(_Op_xfer, &__rhs, &__arg);
	  __arg._M_any = &__rhs;
	  _M_manager(_Op_xfer, this, &__arg);
	  __arg._M_any = this;
	  __tmp._M_manager(_Op_xfer, &__tmp, &__arg);
	}
      else
	{
	  any* __empty = empty() ? this : &__rhs;
	  any* __full = empty() ? &__rhs : this;
	  _Arg __arg;
	  __arg._M_any = __empty;
	  __full->_M_manager(_Op_xfer, __full, &__arg);
	}
    }

    // observers

    /// Reports whether there is a contained object or not.
    _GLIBCXX_NODISCARD bool empty() const noexcept { return _M_manager == nullptr; }

#if __cpp_rtti
    /// The @c typeid of the contained object, or @c typeid(void) if empty.
    const type_info& type() const noexcept
    {
      if (empty())
	return typeid(void);
      _Arg __arg;
      _M_manager(_Op_get_type_info, this, &__arg);
      return *__arg._M_typeinfo;
    }
#endif

    template<typename _Tp>
      static constexpr bool __is_valid_cast()
      { return __or_<is_reference<_Tp>, is_copy_constructible<_Tp>>::value; }

  private:
    enum _Op {
	_Op_access, _Op_get_type_info, _Op_clone, _Op_destroy, _Op_xfer
    };

    union _Arg
    {
	void* _M_obj;
	const std::type_info* _M_typeinfo;
	any* _M_any;
    };

    void (*_M_manager)(_Op, const any*, _Arg*);
    _Storage _M_storage;

    template<typename _Tp>
      friend enable_if_t<is_object<_Tp>::value, void*>
      __any_caster(const any* __any);

    // Manage in-place contained object.
    template<typename _Tp>
      struct _Manager_internal
      {
	static void
	_S_manage(_Op __which, const any* __anyp, _Arg* __arg);

	template<typename _Up>
	  static void
	  _S_create(_Storage& __storage, _Up&& __value)
	  {
	    void* __addr = &__storage._M_buffer;
	    ::new (__addr) _Tp(std::forward<_Up>(__value));
	  }
      };

    // Manage external contained object.
    template<typename _Tp>
      struct _Manager_external
      {
	static void
	_S_manage(_Op __which, const any* __anyp, _Arg* __arg);

	template<typename _Up>
	  static void
	  _S_create(_Storage& __storage, _Up&& __value)
	  {
	    __storage._M_ptr = new _Tp(std::forward<_Up>(__value));
	  }
      };
  };

  /// Exchange the states of two @c any objects.
  inline void swap(any& __x, any& __y) noexcept { __x.swap(__y); }

  /**
   * @brief Access the contained object.
   *
   * @tparam  _ValueType  A const-reference or CopyConstructible type.
   * @param   __any       The object to access.
   * @return  The contained object.
   * @throw   bad_any_cast If <code>
   *          __any.type() != typeid(remove_reference_t<_ValueType>)
   *          </code>
   */
  template<typename _ValueType>
    inline _ValueType any_cast(const any& __any)
    {
      static_assert(any::__is_valid_cast<_ValueType>(),
	  "Template argument must be a reference or CopyConstructible type");
      auto __p = any_cast<add_const_t<remove_reference_t<_ValueType>>>(&__any);
      if (__p)
	return *__p;
      __throw_bad_any_cast();
    }

  /**
   * @brief Access the contained object.
   *
   * @tparam  _ValueType  A reference or CopyConstructible type.
   * @param   __any       The object to access.
   * @return  The contained object.
   * @throw   bad_any_cast If <code>
   *          __any.type() != typeid(remove_reference_t<_ValueType>)
   *          </code>
   *
   * @{
   */
  template<typename _ValueType>
    inline _ValueType any_cast(any& __any)
    {
      static_assert(any::__is_valid_cast<_ValueType>(),
	  "Template argument must be a reference or CopyConstructible type");
      auto __p = any_cast<remove_reference_t<_ValueType>>(&__any);
      if (__p)
	return *__p;
      __throw_bad_any_cast();
    }

  template<typename _ValueType,
           typename enable_if<!is_move_constructible<_ValueType>::value
                              || is_lvalue_reference<_ValueType>::value,
                              bool>::type = true>
    inline _ValueType any_cast(any&& __any)
    {
      static_assert(any::__is_valid_cast<_ValueType>(),
	  "Template argument must be a reference or CopyConstructible type");
      auto __p = any_cast<remove_reference_t<_ValueType>>(&__any);
      if (__p)
	return *__p;
      __throw_bad_any_cast();
    }

  template<typename _ValueType,
           typename enable_if<is_move_constructible<_ValueType>::value
                              && !is_lvalue_reference<_ValueType>::value,
                              bool>::type = false>
    inline _ValueType any_cast(any&& __any)
    {
      static_assert(any::__is_valid_cast<_ValueType>(),
	  "Template argument must be a reference or CopyConstructible type");
      auto __p = any_cast<remove_reference_t<_ValueType>>(&__any);
      if (__p)
	return std::move(*__p);
      __throw_bad_any_cast();
    }
  // @}

  /// @cond undocumented
  template<typename _Tp>
    enable_if_t<is_object<_Tp>::value, void*>
    __any_caster(const any* __any)
    {
      // any_cast<T> returns non-null if __any->type() == typeid(T) and
      // typeid(T) ignores cv-qualifiers so remove them:
      using _Up = remove_cv_t<_Tp>;
      // The contained value has a decayed type, so if decay_t<U> is not U,
      // then it's not possible to have a contained value of type U.
      using __does_not_decay = is_same<decay_t<_Up>, _Up>;
      // Only copy constructible types can be used for contained values.
      using __is_copyable = is_copy_constructible<_Up>;
      // If the type _Tp could never be stored in an any we don't want to
      // instantiate _Manager<_Tp>, so use _Manager<any::_Op> instead, which
      // is explicitly specialized and has a no-op _S_manage function.
      using _Vp = conditional_t<__and_<__does_not_decay, __is_copyable>::value,
				_Up, any::_Op>;
      // First try comparing function addresses, which works without RTTI
      if (__any->_M_manager == &any::_Manager<_Vp>::_S_manage
#if __cpp_rtti
	  || __any->type() == typeid(_Tp)
#endif
	  )
	{
	  any::_Arg __arg;
	  __any->_M_manager(any::_Op_access, __any, &__arg);
	  return __arg._M_obj;
	}
      return nullptr;
    }

  // This overload exists so that std::any_cast<void(*)()>(a) is well-formed.
  template<typename _Tp>
    enable_if_t<!is_object<_Tp>::value, _Tp*>
    __any_caster(const any*) noexcept
    { return nullptr; }
  /// @endcond

  /**
   * @brief Access the contained object.
   *
   * @tparam  _ValueType  The type of the contained object.
   * @param   __any       A pointer to the object to access.
   * @return  The address of the contained object if <code>
   *          __any != nullptr && __any.type() == typeid(_ValueType)
   *          </code>, otherwise a null pointer.
   *
   * @{
   */
  template<typename _ValueType>
    inline const _ValueType* any_cast(const any* __any) noexcept
    {
      if (__any)
	return static_cast<_ValueType*>(__any_caster<_ValueType>(__any));
      return nullptr;
    }

  template<typename _ValueType>
    inline _ValueType* any_cast(any* __any) noexcept
    {
      if (__any)
	return static_cast<_ValueType*>(__any_caster<_ValueType>(__any));
      return nullptr;
    }
  // @}

  template<typename _Tp>
    void
    any::_Manager_internal<_Tp>::
    _S_manage(_Op __which, const any* __any, _Arg* __arg)
    {
      // The contained object is in _M_storage._M_buffer
      auto __ptr = reinterpret_cast<const _Tp*>(&__any->_M_storage._M_buffer);
      switch (__which)
      {
      case _Op_access:
	__arg->_M_obj = const_cast<_Tp*>(__ptr);
	break;
      case _Op_get_type_info:
#if __cpp_rtti
	__arg->_M_typeinfo = &typeid(_Tp);
#endif
	break;
      case _Op_clone:
	::new(&__arg->_M_any->_M_storage._M_buffer) _Tp(*__ptr);
	__arg->_M_any->_M_manager = __any->_M_manager;
	break;
      case _Op_destroy:
	__ptr->~_Tp();
	break;
      case _Op_xfer:
	::new(&__arg->_M_any->_M_storage._M_buffer) _Tp
	  (std::move(*const_cast<_Tp*>(__ptr)));
	__ptr->~_Tp();
	__arg->_M_any->_M_manager = __any->_M_manager;
	const_cast<any*>(__any)->_M_manager = nullptr;
	break;
      }
    }

  template<typename _Tp>
    void
    any::_Manager_external<_Tp>::
    _S_manage(_Op __which, const any* __any, _Arg* __arg)
    {
      // The contained object is *_M_storage._M_ptr
      auto __ptr = static_cast<const _Tp*>(__any->_M_storage._M_ptr);
      switch (__which)
      {
      case _Op_access:
	__arg->_M_obj = const_cast<_Tp*>(__ptr);
	break;
      case _Op_get_type_info:
#if __cpp_rtti
	__arg->_M_typeinfo = &typeid(_Tp);
#endif
	break;
      case _Op_clone:
	__arg->_M_any->_M_storage._M_ptr = new _Tp(*__ptr);
	__arg->_M_any->_M_manager = __any->_M_manager;
	break;
      case _Op_destroy:
	delete __ptr;
	break;
      case _Op_xfer:
	__arg->_M_any->_M_storage._M_ptr = __any->_M_storage._M_ptr;
	__arg->_M_any->_M_manager = __any->_M_manager;
	const_cast<any*>(__any)->_M_manager = nullptr;
	break;
      }
    }

  // Dummy specialization used by __any_caster.
  template<>
    struct any::_Manager_internal<any::_Op>
    {
      static void
      _S_manage(_Op, const any*, _Arg*) { }
    };

  // @} group any
} // namespace fundamentals_v1
} // namespace experimental

_GLIBCXX_END_NAMESPACE_VERSION
} // namespace std

#endif // C++14

#endif // _GLIBCXX_EXPERIMENTAL_ANY
