diff options
author | Ville Voutilainen <ville.voutilainen@gmail.com> | 2016-07-05 21:33:18 +0300 |
---|---|---|
committer | Ville Voutilainen <ville@gcc.gnu.org> | 2016-07-05 21:33:18 +0300 |
commit | 7d4f48b5b85b20df4f1acc19a3f1326d37a8bf6a (patch) | |
tree | bac6ae817f1101d9ed774592f2b848b5c7ffea8f | |
parent | 98d44e93bfde113ced834cc65dd9d11231a94114 (diff) | |
download | gcc-7d4f48b5b85b20df4f1acc19a3f1326d37a8bf6a.zip gcc-7d4f48b5b85b20df4f1acc19a3f1326d37a8bf6a.tar.gz gcc-7d4f48b5b85b20df4f1acc19a3f1326d37a8bf6a.tar.bz2 |
Implement LWG 2509,
any_cast doesn't work with rvalue reference targets and cannot
move with a value target.
* include/experimental/any (any(_ValueType&&)): Constrain and
add an overload that doesn't forward.
(any_cast(any&&)): Constrain and add an overload that moves.
* testsuite/experimental/any/misc/any_cast.cc: Add tests for
the functionality added by LWG 2509.
From-SVN: r238022
-rw-r--r-- | libstdc++-v3/ChangeLog | 11 | ||||
-rw-r--r-- | libstdc++-v3/include/experimental/any | 36 | ||||
-rw-r--r-- | libstdc++-v3/testsuite/experimental/any/misc/any_cast.cc | 30 | ||||
-rw-r--r-- | libstdc++-v3/testsuite/experimental/any/misc/any_cast_neg.cc | 2 |
4 files changed, 76 insertions, 3 deletions
diff --git a/libstdc++-v3/ChangeLog b/libstdc++-v3/ChangeLog index 536e49f..d888864 100644 --- a/libstdc++-v3/ChangeLog +++ b/libstdc++-v3/ChangeLog @@ -1,3 +1,14 @@ +2016-07-05 Ville Voutilainen <ville.voutilainen@gmail.com> + + Implement LWG 2509, + any_cast doesn't work with rvalue reference targets and cannot + move with a value target. + * include/experimental/any (any(_ValueType&&)): Constrain and + add an overload that doesn't forward. + (any_cast(any&&)): Constrain and add an overload that moves. + * testsuite/experimental/any/misc/any_cast.cc: Add tests for + the functionality added by LWG 2509. + 2016-07-04 François Dumont <fdumont@gcc.gnu.org> * testsuite/23_containers/vector/modifiers/emplace/self_emplace.cc: diff --git a/libstdc++-v3/include/experimental/any b/libstdc++-v3/include/experimental/any index ae40091..96ad576 100644 --- a/libstdc++-v3/include/experimental/any +++ b/libstdc++-v3/include/experimental/any @@ -158,7 +158,9 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION /// Construct with a copy of @p __value as the contained object. template <typename _ValueType, typename _Tp = _Decay<_ValueType>, - typename _Mgr = _Manager<_Tp>> + typename _Mgr = _Manager<_Tp>, + typename enable_if<is_constructible<_Tp, _ValueType&&>::value, + bool>::type = true> any(_ValueType&& __value) : _M_manager(&_Mgr::_S_manage) { @@ -167,6 +169,19 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION "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(); } @@ -377,7 +392,10 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION __throw_bad_any_cast(); } - template<typename _ValueType> + 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>(), @@ -387,6 +405,20 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION 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(); + } // @} template<typename _Tp> diff --git a/libstdc++-v3/testsuite/experimental/any/misc/any_cast.cc b/libstdc++-v3/testsuite/experimental/any/misc/any_cast.cc index ce3f213..bb0f754 100644 --- a/libstdc++-v3/testsuite/experimental/any/misc/any_cast.cc +++ b/libstdc++-v3/testsuite/experimental/any/misc/any_cast.cc @@ -77,8 +77,38 @@ void test02() } } +static int move_count = 0; + +void test03() +{ + struct MoveEnabled + { + MoveEnabled(MoveEnabled&&) + { + ++move_count; + } + MoveEnabled() = default; + MoveEnabled(const MoveEnabled&) = default; + }; + MoveEnabled m; + MoveEnabled m2 = any_cast<MoveEnabled>(any(m)); + VERIFY(move_count == 1); + MoveEnabled&& m3 = any_cast<MoveEnabled&&>(any(m)); + VERIFY(move_count == 1); + struct MoveDeleted + { + MoveDeleted(MoveDeleted&&) = delete; + MoveDeleted() = default; + MoveDeleted(const MoveDeleted&) = default; + }; + MoveDeleted md; + MoveDeleted&& md2 = any_cast<MoveDeleted>(any(std::move(md))); + MoveDeleted&& md3 = any_cast<MoveDeleted&&>(any(std::move(md))); +} + int main() { test01(); test02(); + test03(); } diff --git a/libstdc++-v3/testsuite/experimental/any/misc/any_cast_neg.cc b/libstdc++-v3/testsuite/experimental/any/misc/any_cast_neg.cc index 1361db8..82957a1 100644 --- a/libstdc++-v3/testsuite/experimental/any/misc/any_cast_neg.cc +++ b/libstdc++-v3/testsuite/experimental/any/misc/any_cast_neg.cc @@ -26,5 +26,5 @@ void test01() using std::experimental::any_cast; const any y(1); - any_cast<int&>(y); // { dg-error "qualifiers" "" { target { *-*-* } } 353 } + any_cast<int&>(y); // { dg-error "qualifiers" "" { target { *-*-* } } 368 } } |