Implement the missing bits of LWG 2769
authorVille Voutilainen <ville.voutilainen@gmail.com>
Tue, 27 Feb 2018 11:33:30 +0000 (13:33 +0200)
committerVille Voutilainen <ville@gcc.gnu.org>
Tue, 27 Feb 2018 11:33:30 +0000 (13:33 +0200)
* 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
libstdc++-v3/include/std/any
libstdc++-v3/testsuite/20_util/any/misc/any_cast.cc
libstdc++-v3/testsuite/20_util/any/misc/any_cast_neg.cc

index 4f83772b47911c80ad3f1e0109335944e70983eb..05deec4f98e5b39a0c826a374e8b3a5aa513187d 100644 (file)
@@ -1,3 +1,14 @@
+2018-02-27  Ville Voutilainen  <ville.voutilainen@gmail.com>
+
+       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  <jwakely@redhat.com>
 
        PR libstdc++/84532
index 466b7cac129a6c986f0ecfb94a1326b887ded02c..a37eb38d665ddd7463fd50fb3ee47af2336e151f 100644 (file)
@@ -438,8 +438,6 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
       return any(in_place_type<_Tp>, __il, std::forward<_Args>(__args)...);
     }
 
-  template <typename _Tp>
-    using _AnyCast = remove_cv_t<remove_reference_t<_Tp>>;
   /**
    * @brief Access the contained object.
    *
@@ -453,9 +451,12 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
   template<typename _ValueType>
     inline _ValueType any_cast(const any& __any)
     {
+      using _Up = remove_cv_t<remove_reference_t<_ValueType>>;
       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<typename _ValueType>
     inline _ValueType any_cast(any& __any)
     {
+      using _Up = remove_cv_t<remove_reference_t<_ValueType>>;
       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<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<_AnyCast<_ValueType>>(&__any);
-      if (__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 = false>
+  template<typename _ValueType>
     inline _ValueType any_cast(any&& __any)
     {
+      using _Up = remove_cv_t<remove_reference_t<_ValueType>>;
       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();
index 45d8b6307b53cc936e43fa1549d295751662f3d1..37a24d7653a9790480492b01c4d2e299191e225c 100644 (file)
@@ -95,15 +95,6 @@ void test03()
   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)));
 }
 
 void test04()
index 50a9a674c7847530e1170f60c993920118dcaedd..62d7aaa8ca59cc6344623cd2e36c042a9442e3fb 100644 (file)
 
 #include <any>
 
+using std::any;
+using std::any_cast;
+
 void test01()
 {
-  using std::any;
-  using std::any_cast;
-
   const any y(1);
-  any_cast<int&>(y); // { dg-error "invalid static_cast" "" { target { *-*-* } } 460 }
+  any_cast<int&>(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<int&&>(y);
+  // { dg-error "Template argument must be constructible from an lvalue" "" { target { *-*-* } } 483 }
+}
+
+void test03()
+{
+  any y(1);
+  any_cast<int&>(std::move(y));  // { dg-error "invalid static_cast" "" { target { *-*-* } } 501 }
+  // { dg-error "Template argument must be constructible from an rvalue" "" { target { *-*-* } } 497 }
 }