From 5c80f4f6a265df7b6c7f9fe6281abfaf4f5a0c6e Mon Sep 17 00:00:00 2001 From: Marshall Clow Date: Wed, 12 Apr 2017 22:51:27 +0000 Subject: [PATCH] Implement part of LWG#2857 - any/optional. Still to do - variant. Reviewed as https://reviews.llvm.org/D31956 llvm-svn: 300123 --- libcxx/include/any | 28 +++++++++-------- libcxx/include/optional | 12 +++++--- .../any/any.class/any.modifiers/emplace.pass.cpp | 36 ++++++++++++++++------ 3 files changed, 50 insertions(+), 26 deletions(-) diff --git a/libcxx/include/any b/libcxx/include/any index 823e130..d7161b0 100644 --- a/libcxx/include/any +++ b/libcxx/include/any @@ -45,6 +45,10 @@ namespace std { any& operator=(ValueType&& rhs); // 6.3.3 any modifiers + template + decay_t& emplace(Args&&... args); + template + decay_t& emplace(initializer_list, Args&&...); void reset() noexcept; void swap(any& rhs) noexcept; @@ -73,8 +77,6 @@ namespace std { template ValueType* any_cast(any* operand) noexcept; -} // namespace fundamentals_v1 -} // namespace experimental } // namespace std */ @@ -258,7 +260,7 @@ public: is_copy_constructible<_Tp>::value> > _LIBCPP_INLINE_VISIBILITY - void emplace(_Args&&... args); + _Tp& emplace(_Args&&... args); template , @@ -267,7 +269,7 @@ public: is_copy_constructible<_Tp>::value> > _LIBCPP_INLINE_VISIBILITY - void emplace(initializer_list<_Up>, _Args&&...); + _Tp& emplace(initializer_list<_Up>, _Args&&...); // 6.3.3 any modifiers _LIBCPP_INLINE_VISIBILITY @@ -364,9 +366,10 @@ namespace __any_imp template _LIBCPP_INLINE_VISIBILITY - static void __create(any & __dest, _Args&&... __args) { - ::new (static_cast(&__dest.__s.__buf)) _Tp(_VSTD::forward<_Args>(__args)...); + static _Tp& __create(any & __dest, _Args&&... __args) { + _Tp* __ret = ::new (static_cast(&__dest.__s.__buf)) _Tp(_VSTD::forward<_Args>(__args)...); __dest.__h = &_SmallHandler::__handle; + return *__ret; } private: @@ -439,14 +442,15 @@ namespace __any_imp template _LIBCPP_INLINE_VISIBILITY - static void __create(any & __dest, _Args&&... __args) { + static _Tp& __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)...); + _Tp* __ret = ::new ((void*)__hold.get()) _Tp(_VSTD::forward<_Args>(__args)...); __dest.__s.__ptr = __hold.release(); __dest.__h = &_LargeHandler::__handle; + return *__ret; } private: @@ -519,16 +523,16 @@ any & any::operator=(_ValueType && __v) template inline _LIBCPP_INLINE_VISIBILITY -void any::emplace(_Args&&... __args) { +_Tp& any::emplace(_Args&&... __args) { reset(); - __any_imp::_Handler<_Tp>::__create(*this, _VSTD::forward<_Args>(__args)...); + return __any_imp::_Handler<_Tp>::__create(*this, _VSTD::forward<_Args>(__args)...); } template inline _LIBCPP_INLINE_VISIBILITY -void any::emplace(initializer_list<_Up> __il, _Args&&... __args) { +_Tp& any::emplace(initializer_list<_Up> __il, _Args&&... __args) { 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 diff --git a/libcxx/include/optional b/libcxx/include/optional index 10ad31e..118d717 100644 --- a/libcxx/include/optional +++ b/libcxx/include/optional @@ -87,7 +87,7 @@ namespace std { constexpr optional() noexcept; constexpr optional(nullopt_t) noexcept; optional(const optional &); - optional(optional &&) noexcept(see below ); + optional(optional &&) noexcept(see below); template constexpr explicit optional(in_place_t, Args &&...); template constexpr explicit optional(in_place_t, initializer_list, Args &&...); @@ -108,9 +108,9 @@ namespace std { template optional &operator=(U &&); template optional &operator=(const optional &); template optional &operator=(optional &&); - template void emplace(Args &&...); + template T& emplace(Args &&...); template - void emplace(initializer_list, Args &&...); + T& emplace(initializer_list, Args &&...); // 20.6.3.4, swap void swap(optional &) noexcept(see below ); @@ -729,11 +729,12 @@ public: > > _LIBCPP_INLINE_VISIBILITY - void + _Tp & emplace(_Args&&... __args) { reset(); this->__construct(_VSTD::forward<_Args>(__args)...); + return this->__get(); } template > _LIBCPP_INLINE_VISIBILITY - void + _Tp & emplace(initializer_list<_Up> __il, _Args&&... __args) { reset(); this->__construct(__il, _VSTD::forward<_Args>(__args)...); + return this->__get(); } _LIBCPP_INLINE_VISIBILITY diff --git a/libcxx/test/std/utilities/any/any.class/any.modifiers/emplace.pass.cpp b/libcxx/test/std/utilities/any/any.class/any.modifiers/emplace.pass.cpp index 65d94fd..75dfb0a 100644 --- a/libcxx/test/std/utilities/any/any.class/any.modifiers/emplace.pass.cpp +++ b/libcxx/test/std/utilities/any/any.class/any.modifiers/emplace.pass.cpp @@ -11,9 +11,9 @@ // -// template emplace(Args&&...); +// template T& emplace(Args&&...); // template -// void emplace(initializer_list, Args&&...); +// T& emplace(initializer_list, Args&&...); #include #include @@ -42,7 +42,9 @@ void test_emplace_type() { any a(std::in_place_type); assert(Tracked::count == 1); - a.emplace(); + auto &v = a.emplace(); + static_assert( std::is_same_v, "" ); + assert(&v == std::any_cast(&a)); assert(Tracked::count == 0); assert(Type::count == 1); @@ -56,7 +58,9 @@ void test_emplace_type() { any a(std::in_place_type); assert(Tracked::count == 1); - a.emplace(101); + auto &v = a.emplace(101); + static_assert( std::is_same_v, "" ); + assert(&v == std::any_cast(&a)); assert(Tracked::count == 0); assert(Type::count == 1); @@ -70,7 +74,9 @@ void test_emplace_type() { any a(std::in_place_type); assert(Tracked::count == 1); - a.emplace(-1, 42, -1); + auto &v = a.emplace(-1, 42, -1); + static_assert( std::is_same_v, "" ); + assert(&v == std::any_cast(&a)); assert(Tracked::count == 0); assert(Type::count == 1); @@ -89,14 +95,20 @@ void test_emplace_type_tracked() { { any a(std::in_place_type); assert(Tracked::count == 1); - a.emplace(); + auto &v = a.emplace(); + static_assert( std::is_same_v, "" ); + assert(&v == std::any_cast(&a)); + assert(Tracked::count == 0); assertArgsMatch(a); } { any a(std::in_place_type); assert(Tracked::count == 1); - a.emplace(-1, 42, -1); + auto &v = a.emplace(-1, 42, -1); + static_assert( std::is_same_v, "" ); + assert(&v == std::any_cast(&a)); + assert(Tracked::count == 0); assertArgsMatch(a); } @@ -104,7 +116,10 @@ void test_emplace_type_tracked() { { any a(std::in_place_type); assert(Tracked::count == 1); - a.emplace({-1, 42, -1}); + auto &v = a.emplace({-1, 42, -1}); + static_assert( std::is_same_v, "" ); + assert(&v == std::any_cast(&a)); + assert(Tracked::count == 0); assertArgsMatch>(a); } @@ -112,7 +127,10 @@ void test_emplace_type_tracked() { int x = 42; any a(std::in_place_type); assert(Tracked::count == 1); - a.emplace({-1, 42, -1}, x); + auto &v = a.emplace({-1, 42, -1}, x); + static_assert( std::is_same_v, "" ); + assert(&v == std::any_cast(&a)); + assert(Tracked::count == 0); assertArgsMatch, int&>(a); } -- 2.7.4