[libcxx] Add std::any

Summary:
This patch adds std::any by moving/adapting <experimental/any>.

This patch also implements the std::any parts of p0032r3 (http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2016/p0032r3.pdf)
and LWG 2509 (http://cplusplus.github.io/LWG/lwg-defects.html#2509).

I plan to push it in a day or two if there are no comments.


Reviewers: mclow.lists, EricWF

Subscribers: cfe-commits

Differential Revision: https://reviews.llvm.org/D22733

git-svn-id: https://llvm.org/svn/llvm-project/libcxx/trunk@278310 91177308-0d34-0410-b5e6-96231b3b80d8
diff --git a/include/any b/include/any
new file mode 100644
index 0000000..d6ae063
--- /dev/null
+++ b/include/any
@@ -0,0 +1,658 @@
+// -*- C++ -*-
+//===------------------------------ any -----------------------------------===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef _LIBCPP_ANY
+#define _LIBCPP_ANY
+
+/*
+   any synopsis
+
+namespace std {
+
+  class bad_any_cast : public bad_cast
+  {
+  public:
+    virtual const char* what() const noexcept;
+  };
+
+  class any
+  {
+  public:
+
+    // 6.3.1 any construct/destruct
+    any() noexcept;
+
+    any(const any& other);
+    any(any&& other) noexcept;
+
+    template <class ValueType>
+      any(ValueType&& value);
+
+    ~any();
+
+    // 6.3.2 any assignments
+    any& operator=(const any& rhs);
+    any& operator=(any&& rhs) noexcept;
+
+    template <class ValueType>
+      any& operator=(ValueType&& rhs);
+
+    // 6.3.3 any modifiers
+    void reset() noexcept;
+    void swap(any& rhs) noexcept;
+
+    // 6.3.4 any observers
+    bool has_value() const noexcept;
+    const type_info& type() const noexcept;
+  };
+
+   // 6.4 Non-member functions
+  void swap(any& x, any& y) noexcept;
+
+  template <class T, class ...Args>
+    any make_any(Args&& ...args);
+  template <class T, class U, class ...Args>
+    any make_any(initializer_list<U>, Args&& ...args);
+
+  template<class ValueType>
+    ValueType any_cast(const any& operand);
+  template<class ValueType>
+    ValueType any_cast(any& operand);
+  template<class ValueType>
+    ValueType any_cast(any&& operand);
+
+  template<class ValueType>
+    const ValueType* any_cast(const any* operand) noexcept;
+  template<class ValueType>
+    ValueType* any_cast(any* operand) noexcept;
+
+} // namespace fundamentals_v1
+} // namespace experimental
+} // namespace std
+
+*/
+
+#include <experimental/__config>
+#include <memory>
+#include <new>
+#include <typeinfo>
+#include <type_traits>
+#include <cstdlib>
+#include <cassert>
+
+#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER)
+#pragma GCC system_header
+#endif
+
+namespace std {
+class _LIBCPP_EXCEPTION_ABI bad_any_cast : public bad_cast
+{
+public:
+    virtual const char* what() const _NOEXCEPT;
+};
+} // namespace std
+
+_LIBCPP_BEGIN_NAMESPACE_STD
+
+#if _LIBCPP_STD_VER > 14
+
+// Forward declarations
+class _LIBCPP_TYPE_VIS_ONLY any;
+
+template <class _ValueType>
+_LIBCPP_INLINE_VISIBILITY
+add_pointer_t<add_const_t<_ValueType>>
+any_cast(any const *) _NOEXCEPT;
+
+template <class _ValueType>
+_LIBCPP_INLINE_VISIBILITY
+add_pointer_t<_ValueType> any_cast(any *) _NOEXCEPT;
+
+namespace __any_imp
+{
+  using _Buffer = aligned_storage_t<3*sizeof(void*), alignment_of<void*>::value>;
+
+  template <class _Tp>
+  using _IsSmallObject = integral_constant<bool
+        , sizeof(_Tp) <= sizeof(_Buffer)
+          && alignment_of<_Buffer>::value
+             % alignment_of<_Tp>::value == 0
+          && is_nothrow_move_constructible<_Tp>::value
+        >;
+
+  enum class _Action {
+    _Destroy,
+    _Copy,
+    _Move,
+    _Get,
+    _TypeInfo
+  };
+
+  template <class _Tp> struct _SmallHandler;
+  template <class _Tp> struct _LargeHandler;
+
+  template <class _Tp>
+  struct  _LIBCPP_TYPE_VIS_ONLY __unique_typeinfo { static constexpr int __id = 0; };
+  template <class _Tp> constexpr int __unique_typeinfo<_Tp>::__id;
+
+  template <class _Tp>
+  inline _LIBCPP_INLINE_VISIBILITY
+  constexpr const void* __get_fallback_typeid() {
+      return &__unique_typeinfo<decay_t<_Tp>>::__id;
+  }
+
+  template <class _Tp>
+  inline _LIBCPP_INLINE_VISIBILITY
+  bool __compare_typeid(type_info const* __id, const void* __fallback_id)
+  {
+#if !defined(_LIBCPP_NO_RTTI)
+      if (__id && *__id == typeid(_Tp))
+          return true;
+#endif
+      if (!__id && __fallback_id == __any_imp::__get_fallback_typeid<_Tp>())
+          return true;
+      return false;
+  }
+
+  template <class _Tp>
+  using _Handler = conditional_t<
+    _IsSmallObject<_Tp>::value, _SmallHandler<_Tp>, _LargeHandler<_Tp>>;
+
+} // namespace __any_imp
+
+class _LIBCPP_TYPE_VIS_ONLY any
+{
+public:
+  // construct/destruct
+  _LIBCPP_INLINE_VISIBILITY
+  constexpr any() _NOEXCEPT : __h(nullptr) {}
+
+  _LIBCPP_INLINE_VISIBILITY
+  any(any const & __other) : __h(nullptr)
+  {
+    if (__other.__h) __other.__call(_Action::_Copy, this);
+  }
+
+  _LIBCPP_INLINE_VISIBILITY
+  any(any && __other) _NOEXCEPT : __h(nullptr)
+  {
+    if (__other.__h) __other.__call(_Action::_Move, this);
+  }
+
+  template <
+      class _ValueType
+    , class = enable_if_t<
+        !is_same<decay_t<_ValueType>, any>::value &&
+        !__is_inplace_type<_ValueType>::value &&
+        is_copy_constructible<_ValueType>::value>
+    >
+  _LIBCPP_INLINE_VISIBILITY
+  any(_ValueType && __value);
+
+  template <class _Tp, class ..._Args,
+    class = enable_if_t<
+        is_constructible<_Tp, _Args...>::value &&
+        is_copy_constructible<_Tp>::value
+    >
+  >
+  _LIBCPP_INLINE_VISIBILITY
+  explicit any(in_place_type_t<_Tp>, _Args&&... __args);
+
+  template <class _Tp, class _Up, class ..._Args,
+    class = enable_if_t<
+        is_constructible<_Tp, initializer_list<_Up>&, _Args...>::value &&
+        is_copy_constructible<_Tp>::value>
+  >
+  _LIBCPP_INLINE_VISIBILITY
+  explicit any(in_place_type_t<_Tp>, initializer_list<_Up>, _Args&&... __args);
+
+  _LIBCPP_INLINE_VISIBILITY
+  ~any() { this->reset(); }
+
+  // assignments
+  _LIBCPP_INLINE_VISIBILITY
+  any & operator=(any const & __rhs) {
+    any(__rhs).swap(*this);
+    return *this;
+  }
+
+  _LIBCPP_INLINE_VISIBILITY
+  any & operator=(any && __rhs) _NOEXCEPT {
+    any(_VSTD::move(__rhs)).swap(*this);
+    return *this;
+  }
+
+  // TODO: Should this be constrained to disallow in_place types like the
+  // ValueType constructor?
+  template <
+      class _ValueType
+    , class = enable_if_t<
+          !is_same<decay_t<_ValueType>, any>::value
+          && is_copy_constructible<_ValueType>::value
+          && !__is_inplace_type<_ValueType>::value>
+    >
+  _LIBCPP_INLINE_VISIBILITY
+  any & operator=(_ValueType && __rhs);
+
+  template <class _Tp, class ..._Args,
+    class = enable_if_t<
+        is_constructible<_Tp, _Args...>::value &&
+        is_copy_constructible<_Tp>::value>
+    >
+  _LIBCPP_INLINE_VISIBILITY
+  void emplace(_Args&&... args);
+
+  template <class _Tp, class _Up, class ..._Args,
+    class = enable_if_t<
+        is_constructible<_Tp, initializer_list<_Up>&, _Args...>::value &&
+        is_copy_constructible<_Tp>::value>
+  >
+  _LIBCPP_INLINE_VISIBILITY
+  void emplace(initializer_list<_Up>, _Args&&...);
+
+  // 6.3.3 any modifiers
+  _LIBCPP_INLINE_VISIBILITY
+  void reset() _NOEXCEPT { if (__h) this->__call(_Action::_Destroy); }
+
+  _LIBCPP_INLINE_VISIBILITY
+  void swap(any & __rhs) _NOEXCEPT;
+
+  // 6.3.4 any observers
+  _LIBCPP_INLINE_VISIBILITY
+  bool has_value() const _NOEXCEPT { return __h != nullptr; }
+
+#if !defined(_LIBCPP_NO_RTTI)
+  _LIBCPP_INLINE_VISIBILITY
+  const type_info & type() const _NOEXCEPT {
+    if (__h) {
+        return *static_cast<type_info const *>(this->__call(_Action::_TypeInfo));
+    } else {
+        return typeid(void);
+    }
+  }
+#endif
+
+private:
+    typedef __any_imp::_Action _Action;
+    using _HandleFuncPtr =  void* (*)(_Action, any const *, any *, const type_info *,
+      const void* __fallback_info);
+
+    union _Storage {
+        constexpr _Storage() : __ptr(nullptr) {}
+        void *  __ptr;
+        __any_imp::_Buffer __buf;
+    };
+
+    _LIBCPP_ALWAYS_INLINE
+    void * __call(_Action __a, any * __other = nullptr,
+                  type_info const * __info = nullptr,
+                   const void* __fallback_info = nullptr) const
+    {
+        return __h(__a, this, __other, __info, __fallback_info);
+    }
+
+    _LIBCPP_ALWAYS_INLINE
+    void * __call(_Action __a, any * __other = nullptr,
+                  type_info const * __info = nullptr,
+                  const void* __fallback_info = nullptr)
+    {
+        return __h(__a, this, __other, __info, __fallback_info);
+    }
+
+    template <class>
+    friend struct __any_imp::_SmallHandler;
+    template <class>
+    friend struct __any_imp::_LargeHandler;
+
+    template <class _ValueType>
+    friend add_pointer_t<add_const_t<_ValueType>>
+    any_cast(any const *) _NOEXCEPT;
+
+    template <class _ValueType>
+    friend add_pointer_t<_ValueType>
+    any_cast(any *) _NOEXCEPT;
+
+    _HandleFuncPtr __h = nullptr;
+    _Storage __s;
+};
+
+namespace __any_imp
+{
+  template <class _Tp>
+  struct _LIBCPP_TYPE_VIS_ONLY _SmallHandler
+  {
+     _LIBCPP_INLINE_VISIBILITY
+     static void* __handle(_Action __act, any const * __this, any * __other,
+                           type_info const * __info, const void* __fallback_info)
+     {
+        switch (__act)
+        {
+        case _Action::_Destroy:
+          __destroy(const_cast<any &>(*__this));
+          return nullptr;
+        case _Action::_Copy:
+            __copy(*__this, *__other);
+            return nullptr;
+        case _Action::_Move:
+          __move(const_cast<any &>(*__this), *__other);
+          return nullptr;
+        case _Action::_Get:
+            return __get(const_cast<any &>(*__this), __info, __fallback_info);
+        case _Action::_TypeInfo:
+          return __type_info();
+        }
+    }
+
+    template <class ..._Args>
+    _LIBCPP_INLINE_VISIBILITY
+    static void __create(any & __dest, _Args&&... __args) {
+        ::new (static_cast<void*>(&__dest.__s.__buf)) _Tp(_VSTD::forward<_Args>(__args)...);
+        __dest.__h = &_SmallHandler::__handle;
+    }
+
+  private:
+    _LIBCPP_INLINE_VISIBILITY
+    static void __destroy(any & __this) {
+        _Tp & __value = *static_cast<_Tp *>(static_cast<void*>(&__this.__s.__buf));
+        __value.~_Tp();
+        __this.__h = nullptr;
+    }
+
+    _LIBCPP_INLINE_VISIBILITY
+    static void __copy(any const & __this, any & __dest) {
+        _SmallHandler::__create(__dest, *static_cast<_Tp const *>(
+            static_cast<void const *>(&__this.__s.__buf)));
+    }
+
+    _LIBCPP_INLINE_VISIBILITY
+    static void __move(any & __this, any & __dest) {
+        _SmallHandler::__create(__dest, _VSTD::move(
+            *static_cast<_Tp*>(static_cast<void*>(&__this.__s.__buf))));
+        __destroy(__this);
+    }
+
+    _LIBCPP_INLINE_VISIBILITY
+    static void* __get(any & __this,
+                       type_info const * __info,
+                       const void* __fallback_id)
+    {
+        if (__any_imp::__compare_typeid<_Tp>(__info, __fallback_id))
+            return static_cast<void*>(&__this.__s.__buf);
+        return nullptr;
+    }
+
+    _LIBCPP_INLINE_VISIBILITY
+    static void* __type_info()
+    {
+#if !defined(_LIBCPP_NO_RTTI)
+        return const_cast<void*>(static_cast<void const *>(&typeid(_Tp)));
+#else
+        return nullptr;
+#endif
+    }
+  };
+
+  template <class _Tp>
+  struct _LIBCPP_TYPE_VIS_ONLY _LargeHandler
+  {
+    _LIBCPP_INLINE_VISIBILITY
+    static void* __handle(_Action __act, any const * __this,
+                          any * __other, type_info const * __info,
+                          void const* __fallback_info)
+    {
+        switch (__act)
+        {
+        case _Action::_Destroy:
+          __destroy(const_cast<any &>(*__this));
+          return nullptr;
+        case _Action::_Copy:
+          __copy(*__this, *__other);
+          return nullptr;
+        case _Action::_Move:
+          __move(const_cast<any &>(*__this), *__other);
+          return nullptr;
+        case _Action::_Get:
+            return __get(const_cast<any &>(*__this), __info, __fallback_info);
+        case _Action::_TypeInfo:
+          return __type_info();
+        }
+    }
+
+    template <class ..._Args>
+    _LIBCPP_INLINE_VISIBILITY
+    static void __create(any & __dest, _Args&&... __args) {
+        typedef allocator<_Tp> _Alloc;
+        typedef __allocator_destructor<_Alloc> _Dp;
+        _Alloc __a;
+        unique_ptr<_Tp, _Dp> __hold(__a.allocate(1), _Dp(__a, 1));
+        ::new ((void*)__hold.get()) _Tp(_VSTD::forward<_Args>(__args)...);
+        __dest.__s.__ptr = __hold.release();
+        __dest.__h = &_LargeHandler::__handle;
+    }
+
+  private:
+
+    _LIBCPP_INLINE_VISIBILITY
+    static void __destroy(any & __this){
+        delete static_cast<_Tp*>(__this.__s.__ptr);
+        __this.__h = nullptr;
+    }
+
+    _LIBCPP_INLINE_VISIBILITY
+    static void __copy(any const & __this, any & __dest) {
+        _LargeHandler::__create(__dest, *static_cast<_Tp const *>(__this.__s.__ptr));
+    }
+
+    _LIBCPP_INLINE_VISIBILITY
+    static void __move(any & __this, any & __dest) {
+      __dest.__s.__ptr = __this.__s.__ptr;
+      __dest.__h = &_LargeHandler::__handle;
+      __this.__h = nullptr;
+    }
+
+    _LIBCPP_INLINE_VISIBILITY
+    static void* __get(any & __this, type_info const * __info,
+                       void const* __fallback_info)
+    {
+        if (__any_imp::__compare_typeid<_Tp>(__info, __fallback_info))
+            return static_cast<void*>(__this.__s.__ptr);
+        return nullptr;
+
+    }
+
+    _LIBCPP_INLINE_VISIBILITY
+    static void* __type_info()
+    {
+#if !defined(_LIBCPP_NO_RTTI)
+        return const_cast<void*>(static_cast<void const *>(&typeid(_Tp)));
+#else
+        return nullptr;
+#endif
+    }
+  };
+
+} // namespace __any_imp
+
+
+template <class _ValueType, class>
+any::any(_ValueType && __v) : __h(nullptr)
+{
+  typedef typename decay<_ValueType>::type _Tp;
+  static_assert(is_copy_constructible<_Tp>::value,
+                "_ValueType must be CopyConstructible.");
+  using _ForwardTp = conditional_t<
+      is_move_constructible<_Tp>::value, _ValueType, _ValueType&>;
+  typedef __any_imp::_Handler<_Tp> _HandlerType;
+  _HandlerType::__create(*this, _VSTD::forward<_ForwardTp>(__v));
+}
+
+template <class _Tp, class ..._Args, class>
+any::any(in_place_type_t<_Tp>, _Args&&... __args) {
+  using _Hp = __any_imp::_Handler<_Tp>;
+  _Hp::__create(*this, _VSTD::forward<_Args>(__args)...);
+};
+
+template <class _Tp, class _Up, class ..._Args, class>
+any::any(in_place_type_t<_Tp>, initializer_list<_Up> __il, _Args&&... __args) {
+  using _Hp = __any_imp::_Handler<_Tp>;
+  _Hp::__create(*this, __il, _VSTD::forward<_Args>(__args)...);
+}
+
+template <class _ValueType, class>
+inline _LIBCPP_INLINE_VISIBILITY
+any & any::operator=(_ValueType && __v)
+{
+  typedef typename decay<_ValueType>::type _Tp;
+  static_assert(is_copy_constructible<_Tp>::value,
+                "_ValueType must be CopyConstructible.");
+  any(_VSTD::forward<_ValueType>(__v)).swap(*this);
+  return *this;
+}
+
+template <class _Tp, class ..._Args, class>
+inline _LIBCPP_INLINE_VISIBILITY
+void any::emplace(_Args&&... __args) {
+  using _Hp = __any_imp::_Handler<_Tp>;
+  reset();
+  _Hp::__create(*this, _VSTD::forward<_Args>(__args)...);
+}
+
+template <class _Tp, class _Up, class ..._Args, class>
+inline _LIBCPP_INLINE_VISIBILITY
+void any::emplace(initializer_list<_Up> __il, _Args&&... __args) {
+  using _Hp = __any_imp::_Handler<_Tp>;
+  reset();
+  _Hp::__create(*this, __il, _VSTD::forward<_Args>(__args)...);
+}
+
+inline _LIBCPP_INLINE_VISIBILITY
+void any::swap(any & __rhs) _NOEXCEPT
+{
+    if (__h && __rhs.__h) {
+        any __tmp;
+        __rhs.__call(_Action::_Move, &__tmp);
+        this->__call(_Action::_Move, &__rhs);
+        __tmp.__call(_Action::_Move, this);
+    }
+    else if (__h) {
+        this->__call(_Action::_Move, &__rhs);
+    }
+    else if (__rhs.__h) {
+        __rhs.__call(_Action::_Move, this);
+    }
+}
+
+// 6.4 Non-member functions
+
+inline _LIBCPP_INLINE_VISIBILITY
+void swap(any & __lhs, any & __rhs) _NOEXCEPT
+{
+    __lhs.swap(__rhs);
+}
+
+template <class _Tp, class ..._Args>
+inline _LIBCPP_INLINE_VISIBILITY
+any make_any(_Args&&... __args) {
+    return any(in_place<_Tp>, _VSTD::forward<_Args>(__args)...);
+}
+
+template <class _Tp, class _Up, class ..._Args>
+inline _LIBCPP_INLINE_VISIBILITY
+any make_any(initializer_list<_Up> __il, _Args&&... __args) {
+    return any(in_place<_Tp>, __il, _VSTD::forward<_Args>(__args)...);
+}
+
+template <class _ValueType>
+inline _LIBCPP_INLINE_VISIBILITY
+_ValueType any_cast(any const & __v)
+{
+    static_assert(
+        is_reference<_ValueType>::value
+        || is_copy_constructible<_ValueType>::value,
+        "_ValueType is required to be a reference or a CopyConstructible type.");
+    using _Tp = add_const_t<remove_reference_t<_ValueType>>;
+    _Tp * __tmp = _VSTD::any_cast<_Tp>(&__v);
+    if (__tmp == nullptr)
+        __libcpp_throw(bad_any_cast());
+    return *__tmp;
+}
+
+template <class _ValueType>
+inline _LIBCPP_INLINE_VISIBILITY
+_ValueType any_cast(any & __v)
+{
+    static_assert(
+        is_reference<_ValueType>::value
+        || is_copy_constructible<_ValueType>::value,
+        "_ValueType is required to be a reference or a CopyConstructible type.");
+    typedef typename remove_reference<_ValueType>::type _Tp;
+    _Tp * __tmp = _VSTD::any_cast<_Tp>(&__v);
+    if (__tmp == nullptr)
+        __libcpp_throw(bad_any_cast());
+    return *__tmp;
+}
+
+template <class _ValueType>
+inline _LIBCPP_INLINE_VISIBILITY
+_ValueType any_cast(any && __v)
+{
+    static_assert(
+        is_reference<_ValueType>::value
+        || is_copy_constructible<_ValueType>::value,
+        "_ValueType is required to be a reference or a CopyConstructible type.");
+    typedef typename remove_reference<_ValueType>::type _Tp;
+    using _ForwardTp = conditional_t<
+        is_reference<_ValueType>::value,
+        _ValueType,
+        conditional_t<is_move_constructible<_Tp>::value, _Tp, _Tp&>
+    >;
+    _Tp * __tmp = _VSTD::any_cast<_Tp>(&__v);
+    if (__tmp == nullptr)
+        __libcpp_throw(bad_any_cast());
+    return _VSTD::forward<_ForwardTp>(*__tmp);
+}
+
+template <class _ValueType>
+inline _LIBCPP_INLINE_VISIBILITY
+add_pointer_t<add_const_t<_ValueType>>
+any_cast(any const * __any) _NOEXCEPT
+{
+    static_assert(!is_reference<_ValueType>::value,
+                  "_ValueType may not be a reference.");
+    return _VSTD::any_cast<_ValueType>(const_cast<any *>(__any));
+}
+
+template <class _ValueType>
+add_pointer_t<_ValueType>
+any_cast(any * __any) _NOEXCEPT
+{
+    using __any_imp::_Action;
+    static_assert(!is_reference<_ValueType>::value,
+                  "_ValueType may not be a reference.");
+    typedef typename add_pointer<_ValueType>::type _ReturnType;
+    if (__any && __any->__h) {
+        return static_cast<_ReturnType>(
+            __any->__call(_Action::_Get, nullptr,
+#if !defined(_LIBCPP_NO_RTTI)
+                          &typeid(_ValueType),
+#else
+                          nullptr,
+#endif
+                          __any_imp::__get_fallback_typeid<_ValueType>()
+        ));
+    }
+    return nullptr;
+}
+
+#endif // _LIBCPP_STD_VER > 14
+
+_LIBCPP_END_NAMESPACE_STD
+
+#endif // _LIBCPP_ANY