Cross-port the latest resolution of LWG2756 and some bug-fixes to experimental::optional.
authorVille Voutilainen <ville.voutilainen@gmail.com>
Mon, 24 Oct 2016 12:46:44 +0000 (15:46 +0300)
committerVille Voutilainen <ville@gcc.gnu.org>
Mon, 24 Oct 2016 12:46:44 +0000 (15:46 +0300)
Cross-port the latest resolution of LWG2756 and some
bug-fixes to experimental::optional.
PR libstdc++/77288
PR libstdc++/77727
* include/experimental/optional (_Optional_base):
Remove constructors that take a _Tp.
(__is_optional_impl, __is_optional): Remove.
(__converts_from_optional): New.
(optional(_Up&&)): Fix constraints, call base with in_place.
(optional(const optional<_Up>&)): Fix constraints, use emplace.
(optional(optional<_Up>&&)): Likewise.
(operator=(_Up&&)): Fix constraints.
(operator=(const optional<_Up>&)): Likewise.
(operator=(optional<_Up>&&)): Likewise.
(emplace(_Args&&...)): Constrain.
(emplace(initializer_list<_Up>, _Args&&...)): Likewise.
* testsuite/experimental/optional/77288.cc: New.
* testsuite/experimental/optional/assignment/5.cc: Adjust.
* testsuite/experimental/optional/cons/77727.cc: New.
* testsuite/experimental/optional/cons/value.cc: Adjust.

From-SVN: r241476

libstdc++-v3/ChangeLog
libstdc++-v3/include/experimental/optional
libstdc++-v3/testsuite/experimental/optional/77288.cc [new file with mode: 0644]
libstdc++-v3/testsuite/experimental/optional/assignment/5.cc
libstdc++-v3/testsuite/experimental/optional/cons/77727.cc [new file with mode: 0644]
libstdc++-v3/testsuite/experimental/optional/cons/value.cc

index 7d0a0022d62116a9737ac18fa8709ed84e45b74a..1a18edeec77b8b4e60cb7d9afa63c73f9c9d6a97 100644 (file)
@@ -1,3 +1,26 @@
+2016-10-24  Ville Voutilainen  <ville.voutilainen@gmail.com>
+
+       Cross-port the latest resolution of LWG2756 and some
+       bug-fixes to experimental::optional.
+       PR libstdc++/77288
+       PR libstdc++/77727
+       * include/experimental/optional (_Optional_base):
+       Remove constructors that take a _Tp.
+       (__is_optional_impl, __is_optional): Remove.
+       (__converts_from_optional): New.
+       (optional(_Up&&)): Fix constraints, call base with in_place.
+       (optional(const optional<_Up>&)): Fix constraints, use emplace.
+       (optional(optional<_Up>&&)): Likewise.
+       (operator=(_Up&&)): Fix constraints.
+       (operator=(const optional<_Up>&)): Likewise.
+       (operator=(optional<_Up>&&)): Likewise.
+       (emplace(_Args&&...)): Constrain.
+       (emplace(initializer_list<_Up>, _Args&&...)): Likewise.
+       * testsuite/experimental/optional/77288.cc: New.
+       * testsuite/experimental/optional/assignment/5.cc: Adjust.
+       * testsuite/experimental/optional/cons/77727.cc: New.
+       * testsuite/experimental/optional/cons/value.cc: Adjust.
+
 2016-10-24  Jonathan Wakely  <jwakely@redhat.com>
 
        * include/bits/stl_vector.h (vector::_M_data_ptr, vector::data):
index 7191eca98ef6424d7f97d79f169d9d9722fdc5b6..a631158e22d98df2fa2f35814d7e013dd580fb07 100644 (file)
@@ -214,12 +214,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) { }
@@ -356,12 +350,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) { }
@@ -474,19 +462,23 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
   template<typename _Tp>
   class optional;
 
-  template<typename>
-    struct __is_optional_impl : false_type
-    { };
-
-  template<typename _Tp>
-  struct __is_optional_impl<optional<_Tp>> : true_type
-    { };
-
-  template<typename _Tp>
-    struct __is_optional
-    : public __is_optional_impl<std::remove_cv_t<std::remove_reference_t<_Tp>>>
-    { };
-
+  template<typename _Tp, typename _Up>
+    using __converts_from_optional =
+      __or_<is_constructible<_Tp, const optional<_Up>&>,
+           is_constructible<_Tp, optional<_Up>&>,
+           is_constructible<_Tp, const optional<_Up>&&>,
+           is_constructible<_Tp, optional<_Up>&&>,
+           is_convertible<const optional<_Up>&, _Tp>,
+           is_convertible<optional<_Up>&, _Tp>,
+           is_convertible<const optional<_Up>&&, _Tp>,
+           is_convertible<optional<_Up>&&, _Tp>>;
+
+  template<typename _Tp, typename _Up>
+    using __assigns_from_optional =
+      __or_<is_assignable<_Tp&, const optional<_Up>&>,
+           is_assignable<_Tp&, optional<_Up>&>,
+           is_assignable<_Tp&, const optional<_Up>&&>,
+           is_assignable<_Tp&, optional<_Up>&&>>;
 
   /**
     * @brief Class template for optional values.
@@ -522,75 +514,75 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
 
       constexpr optional() = default;
       // Converting constructors for engaged optionals.
-      template <typename _Up,
+      template <typename _Up = _Tp,
                 enable_if_t<__and_<
-                             __not_<is_same<_Tp, _Up>>,
+                             __not_<is_same<optional<_Tp>, 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(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_same<optional<_Tp>, 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(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>
+                           is_convertible<const _Up&, _Tp>,
+                           __not_<__converts_from_optional<_Tp, _Up>>
                            >::value, bool> = true>
       constexpr optional(const optional<_Up>& __t)
-        : _Base(__t ? optional<_Tp>(*__t) : optional<_Tp>()) { }
+      {
+       if (__t)
+         emplace(*__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&>,
-                              __not_<is_convertible<const _Up&, _Tp>>
+                              __not_<is_convertible<const _Up&, _Tp>>,
+                              __not_<__converts_from_optional<_Tp, _Up>>
                               >::value, bool> = false>
       explicit constexpr optional(const optional<_Up>& __t)
-        : _Base(__t ? optional<_Tp>(*__t) : optional<_Tp>()) { }
+      {
+       if (__t)
+         emplace(*__t);
+      }
 
       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>
+                             is_convertible<_Up&&, _Tp>,
+                             __not_<__converts_from_optional<_Tp, _Up>>
                              >::value, bool> = true>
       constexpr optional(optional<_Up>&& __t)
-        : _Base(__t ? optional<_Tp>(std::move(*__t)) : optional<_Tp>()) { }
+      {
+       if (__t)
+         emplace(std::move(*__t));
+      }
 
       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>>
+                           __not_<is_convertible<_Up&&, _Tp>>,
+                           __not_<__converts_from_optional<_Tp, _Up>>
                            >::value, bool> = false>
       explicit constexpr optional(optional<_Up>&& __t)
-        : _Base(__t ? optional<_Tp>(std::move(*__t)) : optional<_Tp>()) { }
+      {
+       if (__t)
+         emplace(std::move(*__t));
+      }
 
       // [X.Y.4.3] (partly) Assignment.
       optional&
@@ -600,18 +592,16 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
         return *this;
       }
 
-      template<typename _Up,
-               enable_if_t<__and_<
-                          __not_<is_same<_Up, nullopt_t>>,
-                          __not_<__is_optional<_Up>>>::value,
-                        bool> = true>
-        optional&
+      template<typename _Up = _Tp>
+        enable_if_t<__and_<
+                     __not_<is_same<optional<_Tp>, decay_t<_Up>>>,
+                     is_constructible<_Tp, _Up>,
+                     __not_<__and_<is_scalar<_Tp>,
+                                   is_same<_Tp, decay_t<_Up>>>>,
+                     is_assignable<_Tp&, _Up>>::value,
+                   optional&>
         operator=(_Up&& __u)
         {
-          static_assert(__and_<is_constructible<_Tp, _Up>,
-                              is_assignable<_Tp&, _Up>>(),
-                        "Cannot assign to value type from argument");
-
           if (this->_M_is_engaged())
             this->_M_get() = std::forward<_Up>(__u);
           else
@@ -620,17 +610,17 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
           return *this;
         }
 
-      template<typename _Up,
-               enable_if_t<__and_<
-                __not_<is_same<_Tp, _Up>>>::value,
-                          bool> = true>
-        optional&
+      template<typename _Up>
+       enable_if_t<__and_<
+                     __not_<is_same<_Tp, _Up>>,
+                     is_constructible<_Tp, const _Up&>,
+                     is_assignable<_Tp&, _Up>,
+                     __not_<__converts_from_optional<_Tp, _Up>>,
+                     __not_<__assigns_from_optional<_Tp, _Up>>
+                     >::value,
+                   optional&>
         operator=(const optional<_Up>& __u)
         {
-          static_assert(__and_<is_constructible<_Tp, _Up>,
-                              is_assignable<_Tp&, _Up>>(),
-                        "Cannot assign to value type from argument");
-
           if (__u)
             {
               if (this->_M_is_engaged())
@@ -645,17 +635,17 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
           return *this;
         }
 
-      template<typename _Up,
-               enable_if_t<__and_<
-                __not_<is_same<_Tp, _Up>>>::value,
-                          bool> = true>
-        optional&
+      template<typename _Up>
+       enable_if_t<__and_<
+                     __not_<is_same<_Tp, _Up>>,
+                     is_constructible<_Tp, _Up>,
+                     is_assignable<_Tp&, _Up>,
+                     __not_<__converts_from_optional<_Tp, _Up>>,
+                     __not_<__assigns_from_optional<_Tp, _Up>>
+                     >::value,
+                   optional&>
         operator=(optional<_Up>&& __u)
         {
-          static_assert(__and_<is_constructible<_Tp, _Up>,
-                              is_assignable<_Tp&, _Up>>(),
-                        "Cannot assign to value type from argument");
-
           if (__u)
             {
               if (this->_M_is_engaged())
@@ -672,18 +662,15 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
         }
 
       template<typename... _Args>
-       void
+       enable_if_t<is_constructible<_Tp, _Args&&...>::value>
        emplace(_Args&&... __args)
        {
-         static_assert(is_constructible<_Tp, _Args&&...>(),
-                       "Cannot emplace value type from arguments");
-
          this->_M_reset();
          this->_M_construct(std::forward<_Args>(__args)...);
        }
 
       template<typename _Up, typename... _Args>
-        enable_if_t<is_constructible<_Tp, initializer_list<_Up>&,
+       enable_if_t<is_constructible<_Tp, initializer_list<_Up>&,
                                     _Args&&...>::value>
        emplace(initializer_list<_Up> __il, _Args&&... __args)
        {
diff --git a/libstdc++-v3/testsuite/experimental/optional/77288.cc b/libstdc++-v3/testsuite/experimental/optional/77288.cc
new file mode 100644 (file)
index 0000000..38b1e85
--- /dev/null
@@ -0,0 +1,405 @@
+// { dg-do run { target c++14 } }
+
+// Copyright (C) 2016 Free Software Foundation, Inc.
+//
+// This file is part of the GNU ISO C++ Library.  This library is free
+// software; you can redistribute it and/or modify it under the
+// terms of the GNU General Public License as published by the
+// Free Software Foundation; either version 3, or (at your option)
+// any later version.
+
+// This library is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+// GNU General Public License for more details.
+
+// You should have received a moved_to of the GNU General Public License along
+// with this library; see the file COPYING3.  If not see
+// <http://www.gnu.org/licenses/>.
+
+#include <experimental/optional>
+#include <experimental/any>
+
+using std::experimental::optional;
+
+#include <testsuite_hooks.h>
+
+void test01()
+{
+    optional<optional<int>> nested_element;
+    optional<int> element = {};
+    nested_element = element;
+    VERIFY(nested_element);
+}
+
+template <class T>
+struct service_result
+{
+  static optional<T> get_result()
+  {
+    T sr;
+    return sr;
+  }
+
+  static optional<T> get_result_with_cond(bool cond)
+  {
+    if (cond)
+      return T{};
+    return {};
+  }
+};
+
+void test02()
+{
+  VERIFY(service_result<int>::get_result());
+  VERIFY(service_result<optional<int>>::get_result());
+  VERIFY(service_result<int>::get_result_with_cond(true));
+  VERIFY(service_result<optional<int>>::get_result_with_cond(true));
+  VERIFY(!service_result<int>::get_result_with_cond(false));
+  VERIFY(!service_result<optional<int>>::get_result_with_cond(false));
+}
+
+struct Widget
+{
+  Widget(int) {}
+  Widget(optional<int>) {}
+};
+
+
+void test03()
+{
+  optional<Widget> w;
+  w = optional<int>();
+  VERIFY(w);
+  static_assert(!std::is_assignable<optional<Widget>&,
+               optional<short>>::value);
+  w = optional<optional<int>>();
+  VERIFY(!w);
+  static_assert(!std::is_assignable<optional<Widget>&,
+               optional<optional<short>>>::value);
+
+  optional<Widget> w2{optional<int>()};
+  VERIFY(w2);
+  optional<Widget> w3  = optional<int>();
+  VERIFY(w3);
+  optional<Widget> w4{optional<short>()};
+  VERIFY(w4);
+  static_assert(!std::is_convertible<optional<short>&&,
+               optional<Widget>>::value);
+
+  optional<Widget> w6{optional<optional<int>>()};
+  VERIFY(!w6);
+  optional<Widget> w7  = optional<optional<int>>();
+  VERIFY(!w7);
+  optional<Widget> w8{optional<optional<short>>()};
+  VERIFY(!w8);
+  static_assert(!std::is_convertible<optional<optional<short>>&&,
+               optional<Widget>>::value);
+  optional<Widget> w10{optional<optional<short>>(10)};
+  VERIFY(w10);
+  optional<Widget> w11 = std::experimental::nullopt;
+  VERIFY(!w11);
+  optional<Widget> w12 = {};
+  VERIFY(!w12);
+  optional<Widget> w13{std::experimental::nullopt};
+  VERIFY(!w13);
+  optional<Widget> w14;
+  w14 = {};
+  VERIFY(!w14);
+}
+
+struct Widget2
+{
+  Widget2(int) {}
+  Widget2(optional<int>) {}
+  Widget2& operator=(int) {return *this;}
+  Widget2& operator=(optional<int>) {return *this;}
+};
+
+void test04()
+{
+  optional<Widget2> w;
+  w = optional<int>();
+  VERIFY(w);
+  w = optional<short>();
+  VERIFY(w);
+  w = optional<optional<int>>();
+  VERIFY(!w);
+  w = optional<optional<short>>();
+  VERIFY(!w);
+  w = optional<optional<short>>(10);
+  optional<Widget2> w2 = std::experimental::nullopt;
+  VERIFY(!w2);
+  optional<Widget2> w3 = {};
+  VERIFY(!w3);
+  optional<Widget2> w4{std::experimental::nullopt};
+  VERIFY(!w4);
+  optional<Widget2> w5;
+  w5 = {};
+  VERIFY(!w5);
+}
+
+struct Thingy
+{
+  Thingy(int) {}
+  Thingy(Widget) {}
+};
+
+void test05()
+{
+  optional<Thingy> ot;
+
+  static_assert(!std::is_assignable<optional<Thingy>&,
+               optional<int>>::value);
+  static_assert(std::is_assignable<optional<Thingy>&,
+               optional<short>>::value);
+  static_assert(!std::is_assignable<optional<Thingy>&,
+               optional<optional<int>>>::value);
+  ot = optional<Widget>();
+  VERIFY(!ot);
+  optional<Thingy> ot2{optional<int>()};
+  VERIFY(ot2);
+  static_assert(!std::is_convertible<optional<int>&&,
+               optional<Thingy>>::value);
+  optional<Thingy> ot3{optional<short>()};
+  VERIFY(!ot3);
+  optional<Thingy> ot4 = optional<short>();
+  VERIFY(!ot4);
+
+  optional<Thingy> ot5{optional<optional<int>>()};
+  VERIFY(!ot5);
+  static_assert(!std::is_convertible<optional<optional<int>>&&,
+               optional<Thingy>>::value);
+
+  optional<Thingy> ot7{optional<Widget>()};
+  VERIFY(!ot7);
+  optional<Thingy> ot8 = optional<Widget>();
+  VERIFY(!ot8);
+  static_assert(!std::is_constructible<optional<Thingy>,
+               optional<optional<short>>>::value);
+  static_assert(!std::is_convertible<optional<optional<short>>,
+               optional<Thingy>>::value);
+  static_assert(!std::is_assignable<optional<Thingy>&,
+               optional<optional<short>>>::value);
+  optional<Thingy> ot9 = std::experimental::nullopt;
+  VERIFY(!ot9);
+  optional<Thingy> ot10 = {};
+  VERIFY(!ot10);
+  optional<Thingy> ot11{std::experimental::nullopt};
+  VERIFY(!ot11);
+  optional<Thingy> ot12;
+  ot12 = {};
+  VERIFY(!ot12);
+}
+
+struct RvalueConstructible
+{
+  RvalueConstructible(int) {}
+  RvalueConstructible(optional<int>&&) {}
+};
+
+void test06()
+{
+  optional<int> oi;
+  optional<RvalueConstructible> ori;
+  static_assert(!std::is_assignable<optional<RvalueConstructible>&,
+               optional<int>&>::value);
+  ori = std::move(oi);
+  VERIFY(ori);
+
+  optional<optional<int>> ooi;
+  static_assert(!std::is_assignable<optional<RvalueConstructible>&,
+               optional<optional<int>>&>::value);
+  ori = std::move(ooi);
+  VERIFY(!ori);
+
+  static_assert(!std::is_constructible<optional<RvalueConstructible>,
+               optional<int>&>::value);
+  static_assert(!std::is_convertible<optional<int>&,
+               optional<RvalueConstructible>>::value);
+
+  optional<RvalueConstructible> ori2(std::move(oi));
+  VERIFY(ori2);
+  optional<RvalueConstructible> ori3 = std::move(oi);
+  VERIFY(ori3);
+
+  static_assert(!std::is_constructible<optional<RvalueConstructible>,
+               optional<optional<int>>&>::value);
+  static_assert(!std::is_convertible<optional<optional<int>>&,
+               optional<RvalueConstructible>>::value);
+  optional<RvalueConstructible> ori6(std::move(ooi));
+  VERIFY(!ori6);
+  optional<RvalueConstructible> ori7 = std::move(ooi);
+  VERIFY(!ori7);
+  optional<RvalueConstructible> ori8 = std::experimental::nullopt;
+  VERIFY(!ori8);
+  optional<RvalueConstructible> ori9 = {};
+  VERIFY(!ori9);
+  optional<RvalueConstructible> ori10{std::experimental::nullopt};
+  VERIFY(!ori10);
+  optional<RvalueConstructible> ori11;
+  ori11 = {};
+  VERIFY(!ori11);
+}
+
+struct Thingy2
+{
+  Thingy2(int) {}
+  explicit Thingy2(optional<int>) {}
+  Thingy2(Widget) {}
+};
+
+void test07()
+{
+  optional<Thingy2> ot{optional<int>{}};
+  VERIFY(ot);
+  static_assert(!std::is_convertible<optional<int>,
+               optional<Thingy2>>::value);
+  optional<Thingy2> ot2{optional<short>{}};
+  VERIFY(ot2);
+  static_assert(!std::is_convertible<optional<short>,
+               optional<Thingy2>>::value);
+  optional<Thingy2> ot3{optional<optional<int>>{}};
+  VERIFY(!ot3);
+  static_assert(!std::is_convertible<optional<optional<int>>,
+               optional<Thingy2>>::value);
+  optional<Thingy2> ot4{optional<optional<short>>{}};
+  VERIFY(!ot4);
+  static_assert(!std::is_convertible<optional<optional<short>>,
+               optional<Thingy2>>::value);
+
+  optional<Thingy2> ot5{optional<Widget>{}};
+  VERIFY(!ot5);
+  optional<Thingy2> ot6 = optional<Widget>();
+  VERIFY(!ot6);
+
+  static_assert(!std::is_assignable<optional<Thingy2>&,
+               optional<int>>::value);
+  static_assert(!std::is_assignable<optional<Thingy2>&,
+               optional<short>>::value);
+  static_assert(!std::is_assignable<optional<Thingy2>&,
+               optional<optional<int>>>::value);
+  static_assert(!std::is_assignable<optional<Thingy2>&,
+               optional<optional<short>>>::value);
+  optional<Thingy2> ot7;
+  ot = optional<Widget>();
+  VERIFY(!ot7);
+  optional<Thingy2> ot8 = std::experimental::nullopt;
+  VERIFY(!ot8);
+  optional<Thingy2> ot9 = {};
+  VERIFY(!ot9);
+  optional<Thingy2> ot10{std::experimental::nullopt};
+  VERIFY(!ot10);
+  optional<Thingy2> ot11;
+  ot11 = {};
+  VERIFY(!ot11);
+}
+
+struct Thingy3
+{
+  Thingy3(int) {}
+  template<class... Args,
+          std::enable_if_t<std::is_constructible<Widget, Args&&...>::value,
+                           bool> = true>
+  explicit Thingy3(Args&&... args) {}
+  Thingy3(Widget) {}
+};
+
+void test08()
+{
+  optional<Thingy3> ot{optional<int>{}};
+  VERIFY(ot);
+  static_assert(!std::is_convertible<optional<int>,
+               optional<Thingy3>>::value);
+  optional<Thingy3> ot2{optional<short>{}};
+  VERIFY(ot2);
+  static_assert(!std::is_convertible<optional<short>,
+               optional<Thingy3>>::value);
+  optional<Thingy3> ot3{optional<optional<int>>{}};
+  VERIFY(!ot3);
+  static_assert(!std::is_convertible<optional<optional<int>>,
+               optional<Thingy3>>::value);
+  optional<Thingy3> ot4{optional<optional<short>>{}};
+  VERIFY(!ot4);
+  static_assert(!std::is_convertible<optional<optional<short>>,
+               optional<Thingy3>>::value);
+
+  optional<Thingy3> ot5{optional<Widget>{}};
+  VERIFY(!ot5);
+  optional<Thingy3> ot6 = optional<Widget>();
+  VERIFY(!ot6);
+
+  static_assert(!std::is_assignable<optional<Thingy3>&,
+               optional<int>>::value);
+  static_assert(!std::is_assignable<optional<Thingy3>&,
+               optional<short>>::value);
+  static_assert(!std::is_assignable<optional<Thingy3>&,
+               optional<optional<int>>>::value);
+  static_assert(!std::is_assignable<optional<Thingy3>&,
+               optional<optional<short>>>::value);
+  optional<Thingy3> ot7;
+  ot = optional<Widget>();
+  VERIFY(!ot7);
+  optional<Thingy3> ot8 = std::experimental::nullopt;
+  VERIFY(!ot8);
+  optional<Thingy3> ot9 = {};
+  VERIFY(!ot9);
+  optional<Thingy3> ot10{std::experimental::nullopt};
+  VERIFY(!ot10);
+  optional<Thingy3> ot11;
+  ot11 = {};
+  VERIFY(!ot11);
+}
+
+void test09()
+{
+  std::experimental::any a = 42;
+  optional<std::experimental::any> oa2 = a;
+  VERIFY(oa2);
+  VERIFY(std::experimental::any_cast<int>(*oa2) == 42);
+  optional<std::experimental::any> oa3 = oa2;
+  VERIFY(oa3);
+  VERIFY(std::experimental::any_cast<int>(*oa3) == 42);
+  optional<std::experimental::any> oa4{oa2};
+  VERIFY(oa4);
+  VERIFY(std::experimental::any_cast<int>(*oa4) == 42);
+  optional<std::experimental::any> oa5(oa2);
+  VERIFY(oa5);
+  VERIFY(std::experimental::any_cast<int>(*oa5) == 42);
+  optional<std::experimental::any> oa6;
+  VERIFY(!oa6);
+  optional<std::experimental::any> oa7 = oa6;
+  VERIFY(!oa7);
+  optional<std::experimental::any> oa8{oa6};
+  VERIFY(!oa8);
+  optional<std::experimental::any> oa9(oa6);
+  VERIFY(!oa9);
+}
+
+void test10()
+{
+  struct X {};
+  optional<int> oi(std::experimental::in_place);
+  oi = {};
+  VERIFY(bool(oi) == false);
+  optional<X> ot(std::experimental::in_place);
+  ot = {};
+  VERIFY(bool(ot) == false);
+  optional<int> oi2(std::experimental::in_place);
+  short int si = 6;
+  oi2 = si;
+}
+
+int main()
+{
+  test01();
+  test02();
+  test03();
+  test04();
+  test05();
+  test06();
+  test07();
+  test08();
+  test09();
+  test10();
+}
index a3d7e851b617c092373c796494dee0ffc48bb2bb..8ee62015bd279a1cdb4a9aeca0acf3e1d154fb9d 100644 (file)
@@ -18,6 +18,7 @@
 // <http://www.gnu.org/licenses/>.
 
 #include <experimental/optional>
+#include <vector>
 #include <testsuite_hooks.h>
 
 int counter = 0;
@@ -61,5 +62,15 @@ int main()
     VERIFY( !o );
   }
 
+  {
+    std::experimental::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 );
 }
diff --git a/libstdc++-v3/testsuite/experimental/optional/cons/77727.cc b/libstdc++-v3/testsuite/experimental/optional/cons/77727.cc
new file mode 100644 (file)
index 0000000..e3abedb
--- /dev/null
@@ -0,0 +1,50 @@
+// { dg-do run { target c++14 } }
+
+// Copyright (C) 2016 Free Software Foundation, Inc.
+//
+// This file is part of the GNU ISO C++ Library.  This library is free
+// software; you can redistribute it and/or modify it under the
+// terms of the GNU General Public License as published by the
+// Free Software Foundation; either version 3, or (at your option)
+// any later version.
+
+// This library is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+// GNU General Public License for more details.
+
+// You should have received a moved_to of the GNU General Public License along
+// with this library; see the file COPYING3.  If not see
+// <http://www.gnu.org/licenses/>.
+
+#include <experimental/optional>
+#include <testsuite_hooks.h>
+
+
+struct NonTransferable
+{
+  int x;
+  NonTransferable(int x) : x(x) {}
+  NonTransferable(NonTransferable&&) = delete;
+  NonTransferable& operator=(NonTransferable&&) = delete;
+  operator int() {return x;}
+};
+
+int main()
+{
+  std::experimental::optional<int> oi;
+  std::experimental::optional<NonTransferable> ot(std::move(oi));
+  VERIFY(!ot);
+
+  std::experimental::optional<int> oi2;
+  std::experimental::optional<NonTransferable> ot2(oi2);
+  VERIFY(!ot);
+
+  std::experimental::optional<int> oi3{42};
+  std::experimental::optional<NonTransferable> ot3(std::move(oi3));
+  VERIFY(ot3 && *ot3 == 42);
+
+  std::experimental::optional<int> oi4{666};
+  std::experimental::optional<NonTransferable> ot4(oi4);
+  VERIFY(ot4 && *ot4 == 666);
+}
index 920b79607295a6bbf2c10b344cab1a678f46b896..81b2cb8dc2e3abc3a1f8bcd1a32d0cd382023a9d 100644 (file)
@@ -254,4 +254,31 @@ int main()
     std::experimental::optional<X> ox4;
     ox4 = oi;
   }
+
+  {
+    std::experimental::optional<std::experimental::optional<int>> ooi =
+      std::experimental::optional<int>();
+    VERIFY(bool(ooi));
+    ooi = std::experimental::optional<int>();
+    VERIFY(bool(ooi));
+    ooi = std::experimental::optional<int>(42);
+    VERIFY(bool(ooi));
+    VERIFY(bool(*ooi));
+    std::experimental::optional<std::experimental::optional<int>> ooi2 =
+      std::experimental::optional<short>();
+    VERIFY(bool(ooi2));
+    ooi2 = std::experimental::optional<short>();
+    VERIFY(bool(ooi2));
+    ooi2 = std::experimental::optional<short>(6);
+    VERIFY(bool(ooi2));
+    VERIFY(bool(*ooi2));
+    std::experimental::optional<std::experimental::optional<int>> ooi3 =
+      std::experimental::optional<int>(42);
+    VERIFY(bool(ooi3));
+    VERIFY(bool(*ooi3));
+    std::experimental::optional<std::experimental::optional<int>> ooi4 =
+      std::experimental::optional<short>(6);
+    VERIFY(bool(ooi4));
+    VERIFY(bool(*ooi4));
+  }
 }