Implement LWG 2509,
authorVille Voutilainen <ville.voutilainen@gmail.com>
Tue, 5 Jul 2016 18:33:18 +0000 (21:33 +0300)
committerVille Voutilainen <ville@gcc.gnu.org>
Tue, 5 Jul 2016 18:33:18 +0000 (21:33 +0300)
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

libstdc++-v3/ChangeLog
libstdc++-v3/include/experimental/any
libstdc++-v3/testsuite/experimental/any/misc/any_cast.cc
libstdc++-v3/testsuite/experimental/any/misc/any_cast_neg.cc

index 536e49f431145b73c9df8145e268841c41a2df22..d888864600e6e07280200c221758d5cc3b5bbe44 100644 (file)
@@ -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:
index ae40091fbb452b8fdfc474e1ea65cafc59c4fe90..96ad5762f66ec4cd54deccd2da4ade50af98caf0 100644 (file)
@@ -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>
index ce3f213588960a08ab9703b7514b6924b4cb4f4b..bb0f754f54943c6df4eea504f24785146ce52122 100644 (file)
@@ -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();
 }
index 1361db89d4c64acaf7b73f46934317d2b03adda2..82957a1f5447eb325de37721054d2bbdf2b379fd 100644 (file)
@@ -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 }
 }