Implement LWG 2857, {variant,optional,any}::emplace should return the constructed...
authorVille Voutilainen <ville.voutilainen@gmail.com>
Wed, 15 Mar 2017 23:13:20 +0000 (01:13 +0200)
committerVille Voutilainen <ville@gcc.gnu.org>
Wed, 15 Mar 2017 23:13:20 +0000 (01:13 +0200)
Implement LWG 2857, {variant,optional,any}::emplace should
return the constructed value.
* include/std/any (emplace(_Args&&...)): Change the return type and
return a reference to the constructed value.
(emplace(initializer_list<_Up>, _Args&&...)): Likewise.
* include/std/optional (emplace(_Args&&...)): Likewise.
(emplace(initializer_list<_Up>, _Args&&...)): Likewise.
* include/std/variant (emplace<_Tp>(_Args&&...)): Likewise.
(emplace<_Tp>(initializer_list<_Up>, _Args&&...)): Likewise.
(emplace<_Np>(_Args&&...)): Likewise.
(emplace<_Np>(initializer_list<_Up>, _Args&&...)): Likewise.
* testsuite/20_util/any/assign/emplace.cc: Add tests for
checking the return value of emplace.
* testsuite/20_util/any/misc/any_cast_neg.cc: Adjust.
* testsuite/20_util/optional/assignment/6.cc: Add tests for
checking the return value of emplace.
* testsuite/20_util/variant/run.cc: Likewise.

From-SVN: r246182

libstdc++-v3/ChangeLog
libstdc++-v3/include/std/any
libstdc++-v3/include/std/optional
libstdc++-v3/include/std/variant
libstdc++-v3/testsuite/20_util/any/assign/emplace.cc
libstdc++-v3/testsuite/20_util/any/misc/any_cast_neg.cc
libstdc++-v3/testsuite/20_util/optional/assignment/6.cc
libstdc++-v3/testsuite/20_util/variant/run.cc

index 59976bd4b74afdccb9aecb336704c0a44a2ccf9d..ec09ea32053147e59ae56ffc01587253c6ded2f6 100644 (file)
@@ -1,3 +1,23 @@
+2017-03-15  Ville Voutilainen  <ville.voutilainen@gmail.com>
+
+       Implement LWG 2857, {variant,optional,any}::emplace should
+       return the constructed value.
+       * include/std/any (emplace(_Args&&...)): Change the return type and
+       return a reference to the constructed value.
+       (emplace(initializer_list<_Up>, _Args&&...)): Likewise.
+       * include/std/optional (emplace(_Args&&...)): Likewise.
+       (emplace(initializer_list<_Up>, _Args&&...)): Likewise.
+       * include/std/variant (emplace<_Tp>(_Args&&...)): Likewise.
+       (emplace<_Tp>(initializer_list<_Up>, _Args&&...)): Likewise.
+       (emplace<_Np>(_Args&&...)): Likewise.
+       (emplace<_Np>(initializer_list<_Up>, _Args&&...)): Likewise.
+       * testsuite/20_util/any/assign/emplace.cc: Add tests for
+       checking the return value of emplace.
+       * testsuite/20_util/any/misc/any_cast_neg.cc: Adjust.
+       * testsuite/20_util/optional/assignment/6.cc: Add tests for
+       checking the return value of emplace.
+       * testsuite/20_util/variant/run.cc: Likewise.
+
 2017-03-15  Xi Ruoyao  <ryxi@stu.xidian.edu.cn>
 
        PR libstdc++/62045
index e807617bdbb8bd590c424b245e687e21fc160ad1..1e84302f0c04b49d41e0b8e6ad237f724501c846 100644 (file)
@@ -268,18 +268,21 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
 
     /// Emplace with an object created from @p __args as the contained object.
     template <typename _ValueType, typename... _Args>
-      typename __any_constructible<void,
+      typename __any_constructible<_Decay<_ValueType>&,
                                   _Decay<_ValueType>, _Args&&...>::type
       emplace(_Args&&... __args)
       {
        __do_emplace<_Decay<_ValueType>>
          (std::forward<_Args>(__args)...);
+       any::_Arg __arg;
+       this->_M_manager(any::_Op_access, this, &__arg);
+       return *static_cast<_Decay<_ValueType>*>(__arg._M_obj);
       }
 
     /// Emplace with an object created from @p __il and @p __args as
     /// the contained object.
     template <typename _ValueType, typename _Up, typename... _Args>
-      typename __any_constructible<void,
+      typename __any_constructible<_Decay<_ValueType>&,
                                   _Decay<_ValueType>,
                                   initializer_list<_Up>,
                                   _Args&&...>::type
@@ -287,6 +290,9 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
       {
        __do_emplace<_Decay<_ValueType>, _Up>
          (__il, std::forward<_Args>(__args)...);
+       any::_Arg __arg;
+       this->_M_manager(any::_Op_access, this, &__arg);
+       return *static_cast<_Decay<_ValueType>*>(__arg._M_obj);
       }
 
     // modifiers
index 5e796ac504d8cf5edbf49809343b5974a54df5f7..3f540ec14b7747b0a377247c7c3d8520c7a964d4 100644 (file)
@@ -592,20 +592,22 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
         }
 
       template<typename... _Args>
-       enable_if_t<is_constructible<_Tp, _Args&&...>::value>
+       enable_if_t<is_constructible<_Tp, _Args&&...>::value, _Tp&>
        emplace(_Args&&... __args)
        {
          this->_M_reset();
          this->_M_construct(std::forward<_Args>(__args)...);
+         return this->_M_get();
        }
 
       template<typename _Up, typename... _Args>
        enable_if_t<is_constructible<_Tp, initializer_list<_Up>&,
-                                    _Args&&...>::value>
+                                    _Args&&...>::value, _Tp&>
        emplace(initializer_list<_Up> __il, _Args&&... __args)
        {
          this->_M_reset();
          this->_M_construct(__il, std::forward<_Args>(__args)...);
+         return this->_M_get();
        }
 
       // Destructor is implicit, implemented in _Optional_base.
index 46d7b92adcfeb62decc12f38d9fd319e234f1b3e..58bf8c7b017a48e0858656f4a6b8d7856a3bc7c0 100644 (file)
@@ -1007,25 +1007,33 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
        }
 
       template<typename _Tp, typename... _Args>
-       enable_if_t<is_constructible_v<_Tp, _Args...> && __exactly_once<_Tp>>
+       enable_if_t<is_constructible_v<_Tp, _Args...> && __exactly_once<_Tp>,
+                   _Tp&>
        emplace(_Args&&... __args)
        {
-         this->emplace<__index_of<_Tp>>(std::forward<_Args>(__args)...);
+         auto& ret =
+           this->emplace<__index_of<_Tp>>(std::forward<_Args>(__args)...);
          __glibcxx_assert(holds_alternative<_Tp>(*this));
+         return ret;
        }
 
       template<typename _Tp, typename _Up, typename... _Args>
        enable_if_t<is_constructible_v<_Tp, initializer_list<_Up>&, _Args...>
-                   && __exactly_once<_Tp>>
+                   && __exactly_once<_Tp>,
+                   _Tp&>
        emplace(initializer_list<_Up> __il, _Args&&... __args)
        {
-         this->emplace<__index_of<_Tp>>(__il, std::forward<_Args>(__args)...);
+         auto& ret =
+           this->emplace<__index_of<_Tp>>(__il,
+                                          std::forward<_Args>(__args)...);
          __glibcxx_assert(holds_alternative<_Tp>(*this));
+         return ret;
        }
 
       template<size_t _Np, typename... _Args>
        enable_if_t<is_constructible_v<variant_alternative_t<_Np, variant>,
-                                      _Args...>>
+                                      _Args...>,
+                   variant_alternative_t<_Np, variant>&>
        emplace(_Args&&... __args)
        {
          static_assert(_Np < sizeof...(_Types),
@@ -1042,11 +1050,13 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
              __throw_exception_again;
            }
          __glibcxx_assert(index() == _Np);
+         return std::get<_Np>(*this);
        }
 
       template<size_t _Np, typename _Up, typename... _Args>
        enable_if_t<is_constructible_v<variant_alternative_t<_Np, variant>,
-                                      initializer_list<_Up>&, _Args...>>
+                                      initializer_list<_Up>&, _Args...>,
+                   variant_alternative_t<_Np, variant>&>
        emplace(initializer_list<_Up> __il, _Args&&... __args)
        {
          static_assert(_Np < sizeof...(_Types),
@@ -1063,6 +1073,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
              __throw_exception_again;
            }
          __glibcxx_assert(index() == _Np);
+         return std::get<_Np>(*this);
        }
 
       constexpr bool valueless_by_exception() const noexcept
index 07cbddeeab6a7ed24e26e768d96d77d8e3715cd5..119104bf553ae8352a000a8ea51ef1013cdfd14f 100644 (file)
@@ -72,4 +72,8 @@ int main()
   std::any o10;
   o10.emplace<char*>(nullptr);
   VERIFY(o9.type() == o10.type());
+  std::any o11;
+  VERIFY(&o11.emplace<int>(42) == &std::any_cast<int&>(o11));
+  VERIFY(&o11.emplace<std::vector<int>>({1,2,3}) ==
+        &std::any_cast<std::vector<int>&>(o11));
 }
index 61f0bc4460ec6be898cde6acfaa8bccac7a12019..2d2b3d3d14c7321c59b87e6813b2cbcfa55d79e2 100644 (file)
@@ -26,5 +26,5 @@ void test01()
   using std::any_cast;
 
   const any y(1);
-  any_cast<int&>(y); // { dg-error "invalid static_cast" "" { target { *-*-* } } 455 }
+  any_cast<int&>(y); // { dg-error "invalid static_cast" "" { target { *-*-* } } 461 }
 }
index 4d754c1e663dfe38ce0b13c4687befe5ef240bb0..40a537a050754a11c556c3d29b1a85c659080804 100644 (file)
@@ -76,6 +76,11 @@ int main()
     o.emplace({ 'a' }, "");
     VERIFY( o && o->state == 2 );
   }
+  {
+    O o;
+    VERIFY(&o.emplace(0) == &*o);
+    VERIFY(&o.emplace({ 'a' }, "") == &*o);
+  }
 
   static_assert( !std::is_constructible<O, std::initializer_list<int>, int>(), "" );
 
index db4529eea3f53b864fe34294678083ed89c4d836..c6c2bc9dc31942e64aceb6c1e1e244354247b41e 100644 (file)
@@ -189,6 +189,15 @@ void emplace()
     try { v.emplace<1>(AlwaysThrow{}); } catch (nullptr_t) { }
     VERIFY(v.valueless_by_exception());
   }
+  VERIFY(&v.emplace<0>(1) == &std::get<0>(v));
+  VERIFY(&v.emplace<int>(1) == &std::get<int>(v));
+  VERIFY(&v.emplace<1>("a") == &std::get<1>(v));
+  VERIFY(&v.emplace<string>("a") == &std::get<string>(v));
+  {
+    variant<vector<int>> v;
+    VERIFY(&v.emplace<0>({1,2,3}) == &std::get<0>(v));
+    VERIFY(&v.emplace<vector<int>>({1,2,3}) == &std::get<vector<int>>(v));
+  }
 }
 
 void test_get()