// <any> -*- C++ -*-
-// Copyright (C) 2014-2016 Free Software Foundation, Inc.
+// 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
#pragma GCC system_header
-#if __cplusplus <= 201402L
-# include <bits/c++17_warning.h>
-#else
+#if __cplusplus >= 201703L
#include <typeinfo>
#include <new>
#endif
}
+#define __cpp_lib_any 201606L
+
/**
* @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.
*/
void __do_emplace(_Args&&... __args)
{
reset();
- _M_manager = &_Mgr::_S_manage;
_Mgr::_S_create(_M_storage, std::forward<_Args>(__args)...);
+ _M_manager = &_Mgr::_S_manage;
}
/// Emplace with an object created from @p __il and @p __args as
void __do_emplace(initializer_list<_Up> __il, _Args&&... __args)
{
reset();
- _M_manager = &_Mgr::_S_manage;
_Mgr::_S_create(_M_storage, __il, std::forward<_Args>(__args)...);
+ _M_manager = &_Mgr::_S_manage;
}
public:
/// Construct with a copy of @p __value as the contained object.
template <typename _ValueType, typename _Tp = _Decay<_ValueType>,
typename _Mgr = _Manager<_Tp>,
- enable_if_t<__and_<is_copy_constructible<_Tp>,
- __not_<is_constructible<_Tp, _ValueType&&>>,
- __not_<__is_in_place_type<_Tp>>>::value,
+ enable_if_t<__and_v<is_copy_constructible<_Tp>,
+ __not_<is_constructible<_Tp, _ValueType&&>>,
+ __not_<__is_in_place_type<_Tp>>>,
bool> = false>
any(_ValueType&& __value)
: _M_manager(&_Mgr::_S_manage)
/// Emplace with an object created from @p __args as the contained object.
template <typename _ValueType, typename... _Args>
- typename __any_constructible<void,
+ typename __any_constructible<_Decay<_ValueType>&,
_Decay<_ValueType>, _Args&&...>::type
emplace(_Args&&... __args)
{
- __do_emplace<_Decay<_ValueType>>
- (std::forward<_Args>(__args)...);
+ __do_emplace<_Decay<_ValueType>>(std::forward<_Args>(__args)...);
+ any::_Arg __arg;
+ this->_M_manager(any::_Op_access, this, &__arg);
+ return *static_cast<_Decay<_ValueType>*>(__arg._M_obj);
}
/// Emplace with an object created from @p __il and @p __args as
/// the contained object.
template <typename _ValueType, typename _Up, typename... _Args>
- typename __any_constructible<void,
+ typename __any_constructible<_Decay<_ValueType>&,
_Decay<_ValueType>,
initializer_list<_Up>,
_Args&&...>::type
emplace(initializer_list<_Up> __il, _Args&&... __args)
{
- __do_emplace<_Decay<_ValueType>, _Up>
- (__il, std::forward<_Args>(__args)...);
+ __do_emplace<_Decay<_ValueType>, _Up>(__il,
+ std::forward<_Args>(__args)...);
+ any::_Arg __arg;
+ this->_M_manager(any::_Op_access, this, &__arg);
+ return *static_cast<_Decay<_ValueType>*>(__arg._M_obj);
}
// modifiers
template<typename _ValueType>
inline _ValueType any_cast(const any& __any)
{
+ using _Up = __remove_cvref_t<_ValueType>;
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);
+ static_assert(is_constructible_v<_ValueType, const _Up&>,
+ "Template argument must be constructible from a const value.");
+ auto __p = any_cast<_Up>(&__any);
if (__p)
- return *__p;
+ return static_cast<_ValueType>(*__p);
__throw_bad_any_cast();
}
template<typename _ValueType>
inline _ValueType any_cast(any& __any)
{
+ using _Up = __remove_cvref_t<_ValueType>;
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);
+ static_assert(is_constructible_v<_ValueType, _Up&>,
+ "Template argument must be constructible from an lvalue.");
+ auto __p = any_cast<_Up>(&__any);
if (__p)
- return *__p;
+ return static_cast<_ValueType>(*__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>
+ template<typename _ValueType>
inline _ValueType any_cast(any&& __any)
{
+ using _Up = __remove_cvref_t<_ValueType>;
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);
+ static_assert(is_constructible_v<_ValueType, _Up>,
+ "Template argument must be constructible from an rvalue.");
+ auto __p = any_cast<_Up>(&__any);
if (__p)
- return std::move(*__p);
+ return static_cast<_ValueType>(std::move(*__p));
__throw_bad_any_cast();
}
// @}
+ /// @cond undocumented
template<typename _Tp>
void* __any_caster(const any* __any)
{
- if (__any->_M_manager != &any::_Manager<decay_t<_Tp>>::_S_manage)
+ // 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:
+ if constexpr (!is_same_v<decay_t<_Up>, _Up>)
return nullptr;
- any::_Arg __arg;
- __any->_M_manager(any::_Op_access, __any, &__arg);
- return __arg._M_obj;
+ // Only copy constructible types can be used for contained values:
+ else if constexpr (!is_copy_constructible_v<_Up>)
+ return nullptr;
+ // First try comparing function addresses, which works without RTTI
+ else if (__any->_M_manager == &any::_Manager<_Up>::_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;
}
+ /// @endcond
/**
* @brief Access the contained object.
template<typename _ValueType>
inline const _ValueType* any_cast(const any* __any) noexcept
{
- if (__any)
- return static_cast<_ValueType*>(__any_caster<_ValueType>(__any));
+ if constexpr (is_object_v<_ValueType>)
+ 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));
+ if constexpr (is_object_v<_ValueType>)
+ if (__any)
+ return static_cast<_ValueType*>(__any_caster<_ValueType>(__any));
return nullptr;
}
// @}
}
/// @}
-
+
+ namespace __detail::__variant
+ {
+ template<typename> struct _Never_valueless_alt; // see <variant>
+
+ // Provide the strong exception-safety guarantee when emplacing an
+ // any into a variant.
+ template<>
+ struct _Never_valueless_alt<std::any>
+ : std::true_type
+ { };
+ } // namespace __detail::__variant
+
_GLIBCXX_END_NAMESPACE_VERSION
} // namespace std
-#endif // C++14
-
+#endif // C++17
#endif // _GLIBCXX_ANY