Implement part of LWG#2857 - any/optional. Still to do - variant. Reviewed as https://reviews.llvm.org/D31956

git-svn-id: https://llvm.org/svn/llvm-project/libcxx/trunk@300123 91177308-0d34-0410-b5e6-96231b3b80d8
This commit is contained in:
Marshall Clow
2017-04-12 22:51:27 +00:00
parent 39683f1377
commit 22381ddf4f
3 changed files with 50 additions and 26 deletions

View File

@@ -45,6 +45,10 @@ namespace std {
any& operator=(ValueType&& rhs); any& operator=(ValueType&& rhs);
// 6.3.3 any modifiers // 6.3.3 any modifiers
template <class ValueType, class... Args>
decay_t<ValueType>& emplace(Args&&... args);
template <class ValueType, class U, class... Args>
decay_t<ValueType>& emplace(initializer_list<U>, Args&&...);
void reset() noexcept; void reset() noexcept;
void swap(any& rhs) noexcept; void swap(any& rhs) noexcept;
@@ -73,8 +77,6 @@ namespace std {
template<class ValueType> template<class ValueType>
ValueType* any_cast(any* operand) noexcept; ValueType* any_cast(any* operand) noexcept;
} // namespace fundamentals_v1
} // namespace experimental
} // namespace std } // namespace std
*/ */
@@ -258,7 +260,7 @@ public:
is_copy_constructible<_Tp>::value> is_copy_constructible<_Tp>::value>
> >
_LIBCPP_INLINE_VISIBILITY _LIBCPP_INLINE_VISIBILITY
void emplace(_Args&&... args); _Tp& emplace(_Args&&... args);
template <class _ValueType, class _Up, class ..._Args, template <class _ValueType, class _Up, class ..._Args,
class _Tp = decay_t<_ValueType>, class _Tp = decay_t<_ValueType>,
@@ -267,7 +269,7 @@ public:
is_copy_constructible<_Tp>::value> is_copy_constructible<_Tp>::value>
> >
_LIBCPP_INLINE_VISIBILITY _LIBCPP_INLINE_VISIBILITY
void emplace(initializer_list<_Up>, _Args&&...); _Tp& emplace(initializer_list<_Up>, _Args&&...);
// 6.3.3 any modifiers // 6.3.3 any modifiers
_LIBCPP_INLINE_VISIBILITY _LIBCPP_INLINE_VISIBILITY
@@ -364,9 +366,10 @@ namespace __any_imp
template <class ..._Args> template <class ..._Args>
_LIBCPP_INLINE_VISIBILITY _LIBCPP_INLINE_VISIBILITY
static void __create(any & __dest, _Args&&... __args) { static _Tp& __create(any & __dest, _Args&&... __args) {
::new (static_cast<void*>(&__dest.__s.__buf)) _Tp(_VSTD::forward<_Args>(__args)...); _Tp* __ret = ::new (static_cast<void*>(&__dest.__s.__buf)) _Tp(_VSTD::forward<_Args>(__args)...);
__dest.__h = &_SmallHandler::__handle; __dest.__h = &_SmallHandler::__handle;
return *__ret;
} }
private: private:
@@ -439,14 +442,15 @@ namespace __any_imp
template <class ..._Args> template <class ..._Args>
_LIBCPP_INLINE_VISIBILITY _LIBCPP_INLINE_VISIBILITY
static void __create(any & __dest, _Args&&... __args) { static _Tp& __create(any & __dest, _Args&&... __args) {
typedef allocator<_Tp> _Alloc; typedef allocator<_Tp> _Alloc;
typedef __allocator_destructor<_Alloc> _Dp; typedef __allocator_destructor<_Alloc> _Dp;
_Alloc __a; _Alloc __a;
unique_ptr<_Tp, _Dp> __hold(__a.allocate(1), _Dp(__a, 1)); unique_ptr<_Tp, _Dp> __hold(__a.allocate(1), _Dp(__a, 1));
::new ((void*)__hold.get()) _Tp(_VSTD::forward<_Args>(__args)...); _Tp* __ret = ::new ((void*)__hold.get()) _Tp(_VSTD::forward<_Args>(__args)...);
__dest.__s.__ptr = __hold.release(); __dest.__s.__ptr = __hold.release();
__dest.__h = &_LargeHandler::__handle; __dest.__h = &_LargeHandler::__handle;
return *__ret;
} }
private: private:
@@ -519,16 +523,16 @@ any & any::operator=(_ValueType && __v)
template <class _ValueType, class ..._Args, class _Tp, class> template <class _ValueType, class ..._Args, class _Tp, class>
inline _LIBCPP_INLINE_VISIBILITY inline _LIBCPP_INLINE_VISIBILITY
void any::emplace(_Args&&... __args) { _Tp& any::emplace(_Args&&... __args) {
reset(); reset();
__any_imp::_Handler<_Tp>::__create(*this, _VSTD::forward<_Args>(__args)...); return __any_imp::_Handler<_Tp>::__create(*this, _VSTD::forward<_Args>(__args)...);
} }
template <class _ValueType, class _Up, class ..._Args, class _Tp, class> template <class _ValueType, class _Up, class ..._Args, class _Tp, class>
inline _LIBCPP_INLINE_VISIBILITY inline _LIBCPP_INLINE_VISIBILITY
void any::emplace(initializer_list<_Up> __il, _Args&&... __args) { _Tp& any::emplace(initializer_list<_Up> __il, _Args&&... __args) {
reset(); reset();
__any_imp::_Handler<_Tp>::__create(*this, __il, _VSTD::forward<_Args>(__args)...); return __any_imp::_Handler<_Tp>::__create(*this, __il, _VSTD::forward<_Args>(__args)...);
} }
inline _LIBCPP_INLINE_VISIBILITY inline _LIBCPP_INLINE_VISIBILITY

View File

@@ -87,7 +87,7 @@ namespace std {
constexpr optional() noexcept; constexpr optional() noexcept;
constexpr optional(nullopt_t) noexcept; constexpr optional(nullopt_t) noexcept;
optional(const optional &); optional(const optional &);
optional(optional &&) noexcept(see below ); optional(optional &&) noexcept(see below);
template <class... Args> constexpr explicit optional(in_place_t, Args &&...); template <class... Args> constexpr explicit optional(in_place_t, Args &&...);
template <class U, class... Args> template <class U, class... Args>
constexpr explicit optional(in_place_t, initializer_list<U>, Args &&...); constexpr explicit optional(in_place_t, initializer_list<U>, Args &&...);
@@ -108,9 +108,9 @@ namespace std {
template <class U = T> optional &operator=(U &&); template <class U = T> optional &operator=(U &&);
template <class U> optional &operator=(const optional<U> &); template <class U> optional &operator=(const optional<U> &);
template <class U> optional &operator=(optional<U> &&); template <class U> optional &operator=(optional<U> &&);
template <class... Args> void emplace(Args &&...); template <class... Args> T& emplace(Args &&...);
template <class U, class... Args> template <class U, class... Args>
void emplace(initializer_list<U>, Args &&...); T& emplace(initializer_list<U>, Args &&...);
// 20.6.3.4, swap // 20.6.3.4, swap
void swap(optional &) noexcept(see below ); void swap(optional &) noexcept(see below );
@@ -729,11 +729,12 @@ public:
> >
> >
_LIBCPP_INLINE_VISIBILITY _LIBCPP_INLINE_VISIBILITY
void _Tp &
emplace(_Args&&... __args) emplace(_Args&&... __args)
{ {
reset(); reset();
this->__construct(_VSTD::forward<_Args>(__args)...); this->__construct(_VSTD::forward<_Args>(__args)...);
return this->__get();
} }
template <class _Up, class... _Args, template <class _Up, class... _Args,
@@ -743,11 +744,12 @@ public:
> >
> >
_LIBCPP_INLINE_VISIBILITY _LIBCPP_INLINE_VISIBILITY
void _Tp &
emplace(initializer_list<_Up> __il, _Args&&... __args) emplace(initializer_list<_Up> __il, _Args&&... __args)
{ {
reset(); reset();
this->__construct(__il, _VSTD::forward<_Args>(__args)...); this->__construct(__il, _VSTD::forward<_Args>(__args)...);
return this->__get();
} }
_LIBCPP_INLINE_VISIBILITY _LIBCPP_INLINE_VISIBILITY

View File

@@ -11,9 +11,9 @@
// <any> // <any>
// template <class T, class ...Args> emplace(Args&&...); // template <class T, class ...Args> T& emplace(Args&&...);
// template <class T, class U, class ...Args> // template <class T, class U, class ...Args>
// void emplace(initializer_list<U>, Args&&...); // T& emplace(initializer_list<U>, Args&&...);
#include <any> #include <any>
#include <cassert> #include <cassert>
@@ -42,7 +42,9 @@ void test_emplace_type() {
any a(std::in_place_type<Tracked>); any a(std::in_place_type<Tracked>);
assert(Tracked::count == 1); assert(Tracked::count == 1);
a.emplace<Type>(); auto &v = a.emplace<Type>();
static_assert( std::is_same_v<Type&, decltype(v)>, "" );
assert(&v == std::any_cast<Type>(&a));
assert(Tracked::count == 0); assert(Tracked::count == 0);
assert(Type::count == 1); assert(Type::count == 1);
@@ -56,7 +58,9 @@ void test_emplace_type() {
any a(std::in_place_type<Tracked>); any a(std::in_place_type<Tracked>);
assert(Tracked::count == 1); assert(Tracked::count == 1);
a.emplace<Type>(101); auto &v = a.emplace<Type>(101);
static_assert( std::is_same_v<Type&, decltype(v)>, "" );
assert(&v == std::any_cast<Type>(&a));
assert(Tracked::count == 0); assert(Tracked::count == 0);
assert(Type::count == 1); assert(Type::count == 1);
@@ -70,7 +74,9 @@ void test_emplace_type() {
any a(std::in_place_type<Tracked>); any a(std::in_place_type<Tracked>);
assert(Tracked::count == 1); assert(Tracked::count == 1);
a.emplace<Type>(-1, 42, -1); auto &v = a.emplace<Type>(-1, 42, -1);
static_assert( std::is_same_v<Type&, decltype(v)>, "" );
assert(&v == std::any_cast<Type>(&a));
assert(Tracked::count == 0); assert(Tracked::count == 0);
assert(Type::count == 1); assert(Type::count == 1);
@@ -89,14 +95,20 @@ void test_emplace_type_tracked() {
{ {
any a(std::in_place_type<Tracked>); any a(std::in_place_type<Tracked>);
assert(Tracked::count == 1); assert(Tracked::count == 1);
a.emplace<Type>(); auto &v = a.emplace<Type>();
static_assert( std::is_same_v<Type&, decltype(v)>, "" );
assert(&v == std::any_cast<Type>(&a));
assert(Tracked::count == 0); assert(Tracked::count == 0);
assertArgsMatch<Type>(a); assertArgsMatch<Type>(a);
} }
{ {
any a(std::in_place_type<Tracked>); any a(std::in_place_type<Tracked>);
assert(Tracked::count == 1); assert(Tracked::count == 1);
a.emplace<Type>(-1, 42, -1); auto &v = a.emplace<Type>(-1, 42, -1);
static_assert( std::is_same_v<Type&, decltype(v)>, "" );
assert(&v == std::any_cast<Type>(&a));
assert(Tracked::count == 0); assert(Tracked::count == 0);
assertArgsMatch<Type, int, int, int>(a); assertArgsMatch<Type, int, int, int>(a);
} }
@@ -104,7 +116,10 @@ void test_emplace_type_tracked() {
{ {
any a(std::in_place_type<Tracked>); any a(std::in_place_type<Tracked>);
assert(Tracked::count == 1); assert(Tracked::count == 1);
a.emplace<Type>({-1, 42, -1}); auto &v = a.emplace<Type>({-1, 42, -1});
static_assert( std::is_same_v<Type&, decltype(v)>, "" );
assert(&v == std::any_cast<Type>(&a));
assert(Tracked::count == 0); assert(Tracked::count == 0);
assertArgsMatch<Type, std::initializer_list<int>>(a); assertArgsMatch<Type, std::initializer_list<int>>(a);
} }
@@ -112,7 +127,10 @@ void test_emplace_type_tracked() {
int x = 42; int x = 42;
any a(std::in_place_type<Tracked>); any a(std::in_place_type<Tracked>);
assert(Tracked::count == 1); assert(Tracked::count == 1);
a.emplace<Type>({-1, 42, -1}, x); auto &v = a.emplace<Type>({-1, 42, -1}, x);
static_assert( std::is_same_v<Type&, decltype(v)>, "" );
assert(&v == std::any_cast<Type>(&a));
assert(Tracked::count == 0); assert(Tracked::count == 0);
assertArgsMatch<Type, std::initializer_list<int>, int&>(a); assertArgsMatch<Type, std::initializer_list<int>, int&>(a);
} }