From 23c3a0590839e94c94890bb11c2e2e96c1b27f1d Mon Sep 17 00:00:00 2001 From: Ville Voutilainen Date: Tue, 27 Feb 2018 13:33:30 +0200 Subject: [PATCH] Implement the missing bits of LWG 2769 * include/std/any (any_cast(const any&)): Add static_assert. (any_cast(any&)): Likewise. (any_cast(any&&)): Likewise, and remove the handling for copyable-but-not-movable type. * testsuite/20_util/any/misc/any_cast.cc: Adjust. * testsuite/20_util/any/misc/any_cast_neg.cc: Likewise, and add new tests. From-SVN: r258031 --- libstdc++-v3/ChangeLog | 11 ++++++ libstdc++-v3/include/std/any | 36 +++++++------------ .../testsuite/20_util/any/misc/any_cast.cc | 9 ----- .../20_util/any/misc/any_cast_neg.cc | 23 +++++++++--- 4 files changed, 43 insertions(+), 36 deletions(-) diff --git a/libstdc++-v3/ChangeLog b/libstdc++-v3/ChangeLog index 4f83772b479..05deec4f98e 100644 --- a/libstdc++-v3/ChangeLog +++ b/libstdc++-v3/ChangeLog @@ -1,3 +1,14 @@ +2018-02-27 Ville Voutilainen + + Implement the missing bits of LWG 2769 + * include/std/any (any_cast(const any&)): Add static_assert. + (any_cast(any&)): Likewise. + (any_cast(any&&)): Likewise, and remove the handling + for copyable-but-not-movable type. + * testsuite/20_util/any/misc/any_cast.cc: Adjust. + * testsuite/20_util/any/misc/any_cast_neg.cc: Likewise, and + add new tests. + 2018-02-23 Jonathan Wakely PR libstdc++/84532 diff --git a/libstdc++-v3/include/std/any b/libstdc++-v3/include/std/any index 466b7cac129..a37eb38d665 100644 --- a/libstdc++-v3/include/std/any +++ b/libstdc++-v3/include/std/any @@ -438,8 +438,6 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION return any(in_place_type<_Tp>, __il, std::forward<_Args>(__args)...); } - template - using _AnyCast = remove_cv_t>; /** * @brief Access the contained object. * @@ -453,9 +451,12 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION template inline _ValueType any_cast(const any& __any) { + using _Up = remove_cv_t>; static_assert(any::__is_valid_cast<_ValueType>(), "Template argument must be a reference or CopyConstructible type"); - auto __p = any_cast<_AnyCast<_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 static_cast<_ValueType>(*__p); __throw_bad_any_cast(); @@ -476,37 +477,26 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION template inline _ValueType any_cast(any& __any) { + using _Up = remove_cv_t>; static_assert(any::__is_valid_cast<_ValueType>(), "Template argument must be a reference or CopyConstructible type"); - auto __p = any_cast<_AnyCast<_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 static_cast<_ValueType>(*__p); __throw_bad_any_cast(); } - template::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<_AnyCast<_ValueType>>(&__any); - if (__p) - return static_cast<_ValueType>(*__p); - __throw_bad_any_cast(); - } - - template::value - && !is_lvalue_reference<_ValueType>::value, - bool>::type = false> + template inline _ValueType any_cast(any&& __any) { + using _Up = remove_cv_t>; static_assert(any::__is_valid_cast<_ValueType>(), "Template argument must be a reference or CopyConstructible type"); - auto __p = any_cast<_AnyCast<_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 static_cast<_ValueType>(std::move(*__p)); __throw_bad_any_cast(); diff --git a/libstdc++-v3/testsuite/20_util/any/misc/any_cast.cc b/libstdc++-v3/testsuite/20_util/any/misc/any_cast.cc index 45d8b6307b5..37a24d7653a 100644 --- a/libstdc++-v3/testsuite/20_util/any/misc/any_cast.cc +++ b/libstdc++-v3/testsuite/20_util/any/misc/any_cast.cc @@ -95,15 +95,6 @@ void test03() VERIFY(move_count == 1); MoveEnabled&& m3 = any_cast(any(m)); VERIFY(move_count == 1); - struct MoveDeleted - { - MoveDeleted(MoveDeleted&&) = delete; - MoveDeleted() = default; - MoveDeleted(const MoveDeleted&) = default; - }; - MoveDeleted md; - MoveDeleted&& md2 = any_cast(any(std::move(md))); - MoveDeleted&& md3 = any_cast(any(std::move(md))); } void test04() diff --git a/libstdc++-v3/testsuite/20_util/any/misc/any_cast_neg.cc b/libstdc++-v3/testsuite/20_util/any/misc/any_cast_neg.cc index 50a9a674c78..62d7aaa8ca5 100644 --- a/libstdc++-v3/testsuite/20_util/any/misc/any_cast_neg.cc +++ b/libstdc++-v3/testsuite/20_util/any/misc/any_cast_neg.cc @@ -20,11 +20,26 @@ #include +using std::any; +using std::any_cast; + void test01() { - using std::any; - using std::any_cast; - const any y(1); - any_cast(y); // { dg-error "invalid static_cast" "" { target { *-*-* } } 460 } + any_cast(y); // { dg-error "invalid static_cast" "" { target { *-*-* } } 461 } + // { dg-error "Template argument must be constructible from a const value" "" { target { *-*-* } } 457 } +} + +void test02() +{ + any y(1); + any_cast(y); + // { dg-error "Template argument must be constructible from an lvalue" "" { target { *-*-* } } 483 } +} + +void test03() +{ + any y(1); + any_cast(std::move(y)); // { dg-error "invalid static_cast" "" { target { *-*-* } } 501 } + // { dg-error "Template argument must be constructible from an rvalue" "" { target { *-*-* } } 497 } } -- 2.30.2