Implement the latest proposed resolution of LWG 2756.
authorVille Voutilainen <ville.voutilainen@gmail.com>
Thu, 18 Aug 2016 20:33:57 +0000 (23:33 +0300)
committerVille Voutilainen <ville@gcc.gnu.org>
Thu, 18 Aug 2016 20:33:57 +0000 (23:33 +0300)
* include/std/optional (Optional_base(const _Tp&))
(Optional_base(_Tp&&), using _Base::_Base): Remove.
(optional(nullopt_t)): New.
(optional(_Up&&)): Invoke base directly with in_place
rather than creating a temporary, add default template
argument, change constraints.
(optional(const optional<_Up>&)): Invoke base directly
with in_place, remove unnecessary constraints.
(optional(optional<_Up>&& __t)): Likewise.
(optional(in_place_t, _Args&&...)): New.
(optional(in_place_t, initializer_list<_Up>, _Args&&...)): Likewise.
(operator=(_Up&&)): Add default template argument, change constraints.
(operator=(const optional<_Up>&)): Put is_same first in the
constraints.
(operator=(optional<_Up>&&)): Likewise.
* testsuite/20_util/optional/assignment/5.cc: Add a test to
verify assignment from something that can't be perfect-forwarded.
* testsuite/20_util/optional/cons/value.cc: Add tests to verify
that a nested optional is disengaged when constructed
from a disengaged element type, and to verify that assignments
from an engaged element type engage the optional.

From-SVN: r239593

libstdc++-v3/ChangeLog
libstdc++-v3/include/std/optional
libstdc++-v3/testsuite/20_util/optional/assignment/5.cc
libstdc++-v3/testsuite/20_util/optional/cons/value.cc

index a2fa63e67620d50bdfc916f66d0664d908f144c5..e8eebd39e7eb1997ad72aebf702e19b08cbe8692 100644 (file)
@@ -1,3 +1,28 @@
+2016-08-18  Ville Voutilainen  <ville.voutilainen@gmail.com>
+
+       Implement the latest proposed resolution of LWG 2756.
+       * include/std/optional (Optional_base(const _Tp&))
+       (Optional_base(_Tp&&), using _Base::_Base): Remove.
+       (optional(nullopt_t)): New.
+       (optional(_Up&&)): Invoke base directly with in_place
+       rather than creating a temporary, add default template
+       argument, change constraints.
+       (optional(const optional<_Up>&)): Invoke base directly
+       with in_place, remove unnecessary constraints.
+       (optional(optional<_Up>&& __t)): Likewise.
+       (optional(in_place_t, _Args&&...)): New.
+       (optional(in_place_t, initializer_list<_Up>, _Args&&...)): Likewise.
+       (operator=(_Up&&)): Add default template argument, change constraints.
+       (operator=(const optional<_Up>&)): Put is_same first in the
+       constraints.
+       (operator=(optional<_Up>&&)): Likewise.
+       * testsuite/20_util/optional/assignment/5.cc: Add a test to
+       verify assignment from something that can't be perfect-forwarded.
+       * testsuite/20_util/optional/cons/value.cc: Add tests to verify
+       that a nested optional is disengaged when constructed
+       from a disengaged element type, and to verify that assignments
+       from an engaged element type engage the optional.
+
 2016-08-18  Tim Shen  <timshen@google.com>
 
        Implement <variant>
index 4c94dff00d16be69a340513d334ecf949508bc1f..2ff75eae638735899c15fdc13e5afeef2d3ab0e8 100644 (file)
@@ -175,12 +175,6 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
       : _Optional_base{} { }
 
       // Constructors for engaged optionals.
-      constexpr _Optional_base(const _Tp& __t)
-      : _M_payload(__t), _M_engaged(true) { }
-
-      constexpr _Optional_base(_Tp&& __t)
-      : _M_payload(std::move(__t)), _M_engaged(true) { }
-
       template<typename... _Args>
         constexpr explicit _Optional_base(in_place_t, _Args&&... __args)
         : _M_payload(std::forward<_Args>(__args)...), _M_engaged(true) { }
@@ -317,12 +311,6 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
       constexpr _Optional_base(nullopt_t) noexcept
       : _Optional_base{} { }
 
-      constexpr _Optional_base(const _Tp& __t)
-      : _M_payload(__t), _M_engaged(true) { }
-
-      constexpr _Optional_base(_Tp&& __t)
-      : _M_payload(std::move(__t)), _M_engaged(true) { }
-
       template<typename... _Args>
         constexpr explicit _Optional_base(in_place_t, _Args&&... __args)
         : _M_payload(std::forward<_Args>(__args)...), _M_engaged(true) { }
@@ -478,80 +466,79 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
     public:
       using value_type = _Tp;
 
-      // _Optional_base has the responsibility for construction.
-      using _Base::_Base;
-
       constexpr optional() = default;
+
+      constexpr optional(nullopt_t) noexcept
+       : _Base(nullopt) { }
+
       // Converting constructors for engaged optionals.
-      template <typename _Up,
+      template <typename _Up = _Tp,
                 enable_if_t<__and_<
-                             __not_<is_same<_Tp, _Up>>,
+                             __not_<__is_optional<decay_t<_Up>>>,
                              is_constructible<_Tp, _Up&&>,
                              is_convertible<_Up&&, _Tp>
                              >::value, bool> = true>
       constexpr optional(_Up&& __t)
-        : _Base(_Tp(std::forward<_Up>(__t))) { }
+        : _Base(std::in_place, std::forward<_Up>(__t)) { }
 
-      template <typename _Up,
+      template <typename _Up = _Tp,
                 enable_if_t<__and_<
-                           __not_<is_same<_Tp, _Up>>,
-                           is_constructible<_Tp, _Up&&>,
-                           __not_<is_convertible<_Up&&, _Tp>>
-                           >::value, bool> = false>
+                             __not_<__is_optional<decay_t<_Up>>>,
+                             is_constructible<_Tp, _Up&&>,
+                             __not_<is_convertible<_Up&&, _Tp>>
+                             >::value, bool> = false>
       explicit constexpr optional(_Up&& __t)
-        : _Base(_Tp(std::forward<_Up>(__t))) { }
+        : _Base(std::in_place, std::forward<_Up>(__t)) { }
 
       template <typename _Up,
                 enable_if_t<__and_<
                            __not_<is_same<_Tp, _Up>>,
-                           __not_<is_constructible<
-                             _Tp, const optional<_Up>&>>,
-                           __not_<is_convertible<
-                             const optional<_Up>&, _Tp>>,
                            is_constructible<_Tp, const _Up&>,
                            is_convertible<const _Up&, _Tp>
                            >::value, bool> = true>
       constexpr optional(const optional<_Up>& __t)
-        : _Base(__t ? optional<_Tp>(*__t) : optional<_Tp>()) { }
+        : _Base(__t ? _Base(std::in_place, *__t) : _Base()) { }
 
       template <typename _Up,
                  enable_if_t<__and_<
                               __not_<is_same<_Tp, _Up>>,
-                              __not_<is_constructible<
-                                       _Tp, const optional<_Up>&>>,
-                              __not_<is_convertible<
-                                const optional<_Up>&, _Tp>>,
                               is_constructible<_Tp, const _Up&>,
                               __not_<is_convertible<const _Up&, _Tp>>
                               >::value, bool> = false>
       explicit constexpr optional(const optional<_Up>& __t)
-        : _Base(__t ? optional<_Tp>(*__t) : optional<_Tp>()) { }
+        : _Base(__t ? _Base(std::in_place, *__t) : _Base()) { }
 
       template <typename _Up,
                 enable_if_t<__and_<
                              __not_<is_same<_Tp, _Up>>,
-                             __not_<is_constructible<
-                                      _Tp, optional<_Up>&&>>,
-                             __not_<is_convertible<
-                                      optional<_Up>&&, _Tp>>,
                              is_constructible<_Tp, _Up&&>,
                              is_convertible<_Up&&, _Tp>
                              >::value, bool> = true>
       constexpr optional(optional<_Up>&& __t)
-        : _Base(__t ? optional<_Tp>(std::move(*__t)) : optional<_Tp>()) { }
+        : _Base(__t ? _Base(std::in_place, std::move(*__t)) : _Base()) { }
 
       template <typename _Up,
                 enable_if_t<__and_<
                            __not_<is_same<_Tp, _Up>>,
-                           __not_<is_constructible<
-                                    _Tp, optional<_Up>&&>>,
-                           __not_<is_convertible<
-                                    optional<_Up>&&, _Tp>>,
                            is_constructible<_Tp, _Up&&>,
                            __not_<is_convertible<_Up&&, _Tp>>
                            >::value, bool> = false>
       explicit constexpr optional(optional<_Up>&& __t)
-        : _Base(__t ? optional<_Tp>(std::move(*__t)) : optional<_Tp>()) { }
+        : _Base(__t ? _Base(std::in_place, std::move(*__t)) : _Base()) { }
+
+      template<typename... _Args>
+      explicit constexpr optional(in_place_t, _Args&&... __args)
+        : _Base(std::in_place, std::forward<_Args>(__args)...) { }
+
+      template<typename _Up, typename... _Args,
+               enable_if_t<is_constructible<_Tp,
+                                            initializer_list<_Up>&,
+                                            _Args&&...>::value,
+                           int>...>
+      explicit constexpr optional(in_place_t,
+                                 initializer_list<_Up> __il,
+                                 _Args&&... __args)
+        : _Base(std::in_place, __il, std::forward<_Args>(__args)...) { }
 
       // Assignment operators.
       optional&
@@ -561,13 +548,12 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
         return *this;
       }
 
-      template<typename _Up,
+      template<typename _Up = _Tp,
                enable_if_t<__and_<
-                          is_constructible<_Tp, _Up>,
-                          is_assignable<_Tp&, _Up>,
-                          __not_<is_same<_Up, nullopt_t>>,
-                          __not_<__is_optional<_Up>>>::value,
-                        bool> = true>
+                            __not_<__is_optional<decay_t<_Up>>>,
+                            is_constructible<_Tp, _Up>,
+                            is_assignable<_Tp&, _Up>>::value,
+                          bool> = true>
         optional&
         operator=(_Up&& __u)
         {
@@ -581,10 +567,10 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
 
       template<typename _Up,
                enable_if_t<__and_<
-                          is_constructible<_Tp, _Up>,
-                          is_assignable<_Tp&, _Up>,
-                          __not_<is_same<_Tp, _Up>>>::value,
-                        bool> = true>
+                            __not_<is_same<_Tp, _Up>>,
+                            is_constructible<_Tp, _Up>,
+                            is_assignable<_Tp&, _Up>>::value,
+                          bool> = true>
         optional&
         operator=(const optional<_Up>& __u)
         {
@@ -604,10 +590,10 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
 
       template<typename _Up,
               enable_if_t<__and_<
-                          is_constructible<_Tp, _Up>,
-                          is_assignable<_Tp&, _Up>,
-                          __not_<is_same<_Tp, _Up>>>::value,
-                        bool> = true>
+                            __not_<is_same<_Tp, _Up>>,
+                            is_constructible<_Tp, _Up>,
+                            is_assignable<_Tp&, _Up>>::value,
+                          bool> = true>
         optional&
         operator=(optional<_Up>&& __u)
         {
index e450a4613994f7e7b591afbe2936c2362c95320b..d1a75b49ac79b1943bb7ff112a483b3534aec413 100644 (file)
@@ -19,6 +19,7 @@
 // <http://www.gnu.org/licenses/>.
 
 #include <optional>
+#include <vector>
 #include <testsuite_hooks.h>
 
 int counter = 0;
@@ -61,6 +62,14 @@ int main()
     o = {};
     VERIFY( !o );
   }
-
+  {
+    std::optional<std::vector<int>> ovi{{1, 2, 3}};
+    VERIFY(ovi->size() == 3);
+    VERIFY((*ovi)[0] == 1 && (*ovi)[1] == 2 && (*ovi)[2] == 3);
+    ovi = {4, 5, 6, 7};
+    VERIFY(ovi->size() == 4);
+    VERIFY((*ovi)[0] == 4 && (*ovi)[1] == 5 &&
+          (*ovi)[2] == 6 && (*ovi)[3] == 7);
+  }
   VERIFY( counter == 0 );
 }
index 13a6e9ca4dd6a1d1b89ef3b7a1f6e88a7fb30411..6a2d8716aee42e0b1b05db2134d1e026c0446ea3 100644 (file)
@@ -255,4 +255,26 @@ int main()
     std::optional<X> ox4;
     ox4 = oi;
   }
+  {
+    std::optional<std::optional<int>> ooi = std::optional<int>();
+    VERIFY(!bool(ooi));
+    ooi = std::optional<int>();
+    VERIFY(!bool(ooi));
+    ooi = std::optional<int>(42);
+    VERIFY(bool(ooi));
+    VERIFY(bool(*ooi));
+    std::optional<std::optional<int>> ooi2 = std::optional<short>();
+    VERIFY(!bool(ooi2));
+    ooi2 = std::optional<short>();
+    VERIFY(!bool(ooi2));
+    ooi2 = std::optional<short>(6);
+    VERIFY(bool(ooi2));
+    VERIFY(bool(*ooi2));
+    std::optional<std::optional<int>> ooi3 = std::optional<int>(42);
+    VERIFY(bool(ooi3));
+    VERIFY(bool(*ooi3));
+    std::optional<std::optional<int>> ooi4 = std::optional<short>(6);
+    VERIFY(bool(ooi4));
+    VERIFY(bool(*ooi4));
+  }
 }