Implement P0032R3, Homogeneous interface for variant, any and optional,
authorVille Voutilainen <ville.voutilainen@gmail.com>
Thu, 14 Jul 2016 09:10:05 +0000 (12:10 +0300)
committerVille Voutilainen <ville@gcc.gnu.org>
Thu, 14 Jul 2016 09:10:05 +0000 (12:10 +0300)
for the parts concerning any and optional.
* include/std/any (_Storage()): Make constexpr and have it
initialize _M_ptr.
(any()): Make constexpr.
(any(const any&)): Adjust.
(any(any&&)): Likewise.
(__any_constructible_t): New.
(any(_ValueType&&)): Constrain.
(any(in_place_type_t<_Tp>, _Args&&...)): New.
(any(in_place_type_t<_Tp>, initializer_list<_Up>, _Args&&...)):
Likewise.
(~any()): Adjust.
(operator=(const any&)): Likewise.
(operator=(any&&)): Likewise.
(operator=(_ValueType&&)): Constrain.
(emplace(_Args&&...)): New.
(emplace(initializer_list<_Up>, _Args&&...)): Likewise.
(clear()): Remove.
(reset()): New.
(swap(any&)): Adjust.
(empty()): Remove.
(has_value()): New.
(type()): Adjust.
(_Manager_internal::_S_create(_Storage&, _Args&&...)): New.
(_Manager_external::_S_create(_Storage&, _Args&&...)): Likewise.
(make_any(_Args&&...)): Likewise.
(make_any(initializer_list<_Up>, _Args&&...)): Likewise.
* include/std/optional (in_place_t, in_place): Remove.
(bad_optional_access): Add a comment referring to LEWG 72.
(emplace(_Args&&...)): Constrain.
(has_value()): New.
(reset()): Likewise.
(make_optional(_Args&&...)): Likewise.
(make_optional(initializer_list<_Up>, _Args&&...)): Likewise.
* include/std/utility (in_place_tag): New.
(__in_place, __in_place_type, __in_place_index): Likewise.
(in_place_t, in_place_type_t, in_place_index_t): Likewise.
(in_place(__in_place*)): Likewise.
(in_place(__in_place_type<_Tp>*)): Likewise.
(in_place(__in_place_index<_Idx>*)): Likewise.
* testsuite/20_util/any/assign/1.cc: Adjust.
* testsuite/20_util/any/assign/emplace.cc: New.
* testsuite/20_util/any/assign/self.cc: Adjust.
* testsuite/20_util/any/cons/1.cc: Likewise.
* testsuite/20_util/any/cons/in_place.cc: New.
* testsuite/20_util/any/make_any.cc: Likewise.
* testsuite/20_util/any/misc/any_cast_neg.cc: Adjust.
* testsuite/20_util/any/misc/swap.cc: Likewise.
* testsuite/20_util/any/modifiers/1.cc: Likewise.
* testsuite/20_util/any/requirements.cc: New.
* testsuite/20_util/in_place/requirements.cc: Likewise.
* testsuite/20_util/optional/constexpr/in_place.cc: Adjust.
* testsuite/20_util/optional/in_place.cc: Likewise.
* testsuite/20_util/optional/make_optional.cc: Add tests for
the new overloads of make_optional.

From-SVN: r238329

18 files changed:
libstdc++-v3/ChangeLog
libstdc++-v3/include/std/any
libstdc++-v3/include/std/optional
libstdc++-v3/include/std/utility
libstdc++-v3/testsuite/20_util/any/assign/1.cc
libstdc++-v3/testsuite/20_util/any/assign/emplace.cc [new file with mode: 0644]
libstdc++-v3/testsuite/20_util/any/assign/self.cc
libstdc++-v3/testsuite/20_util/any/cons/1.cc
libstdc++-v3/testsuite/20_util/any/cons/in_place.cc [new file with mode: 0644]
libstdc++-v3/testsuite/20_util/any/make_any.cc [new file with mode: 0644]
libstdc++-v3/testsuite/20_util/any/misc/any_cast_neg.cc
libstdc++-v3/testsuite/20_util/any/misc/swap.cc
libstdc++-v3/testsuite/20_util/any/modifiers/1.cc
libstdc++-v3/testsuite/20_util/any/requirements.cc [new file with mode: 0644]
libstdc++-v3/testsuite/20_util/in_place/requirements.cc [new file with mode: 0644]
libstdc++-v3/testsuite/20_util/optional/constexpr/in_place.cc
libstdc++-v3/testsuite/20_util/optional/in_place.cc
libstdc++-v3/testsuite/20_util/optional/make_optional.cc

index 70ad53a0531f545821f56c4907d800c7ed47e084..a34ca2187975147ca56fc3f3cdf46b5bf21ee821 100644 (file)
@@ -1,3 +1,62 @@
+2016-07-14  Ville Voutilainen  <ville.voutilainen@gmail.com>
+
+       Implement P0032R3, Homogeneous interface for variant, any and optional,
+       for the parts concerning any and optional.
+       * include/std/any (_Storage()): Make constexpr and have it
+       initialize _M_ptr.
+       (any()): Make constexpr.
+       (any(const any&)): Adjust.
+       (any(any&&)): Likewise.
+       (__any_constructible_t): New.
+       (any(_ValueType&&)): Constrain.
+       (any(in_place_type_t<_Tp>, _Args&&...)): New.
+       (any(in_place_type_t<_Tp>, initializer_list<_Up>, _Args&&...)):
+       Likewise.
+       (~any()): Adjust.
+       (operator=(const any&)): Likewise.
+       (operator=(any&&)): Likewise.
+       (operator=(_ValueType&&)): Constrain.
+       (emplace(_Args&&...)): New.
+       (emplace(initializer_list<_Up>, _Args&&...)): Likewise.
+       (clear()): Remove.
+       (reset()): New.
+       (swap(any&)): Adjust.
+       (empty()): Remove.
+       (has_value()): New.
+       (type()): Adjust.
+       (_Manager_internal::_S_create(_Storage&, _Args&&...)): New.
+       (_Manager_external::_S_create(_Storage&, _Args&&...)): Likewise.
+       (make_any(_Args&&...)): Likewise.
+       (make_any(initializer_list<_Up>, _Args&&...)): Likewise.
+       * include/std/optional (in_place_t, in_place): Remove.
+       (bad_optional_access): Add a comment referring to LEWG 72.
+       (emplace(_Args&&...)): Constrain.
+       (has_value()): New.
+       (reset()): Likewise.
+       (make_optional(_Args&&...)): Likewise.
+       (make_optional(initializer_list<_Up>, _Args&&...)): Likewise.
+       * include/std/utility (in_place_tag): New.
+       (__in_place, __in_place_type, __in_place_index): Likewise.
+       (in_place_t, in_place_type_t, in_place_index_t): Likewise.
+       (in_place(__in_place*)): Likewise.
+       (in_place(__in_place_type<_Tp>*)): Likewise.
+       (in_place(__in_place_index<_Idx>*)): Likewise.
+       * testsuite/20_util/any/assign/1.cc: Adjust.
+       * testsuite/20_util/any/assign/emplace.cc: New.
+       * testsuite/20_util/any/assign/self.cc: Adjust.
+       * testsuite/20_util/any/cons/1.cc: Likewise.
+       * testsuite/20_util/any/cons/in_place.cc: New.
+       * testsuite/20_util/any/make_any.cc: Likewise.
+       * testsuite/20_util/any/misc/any_cast_neg.cc: Adjust.
+       * testsuite/20_util/any/misc/swap.cc: Likewise.
+       * testsuite/20_util/any/modifiers/1.cc: Likewise.
+       * testsuite/20_util/any/requirements.cc: New.
+       * testsuite/20_util/in_place/requirements.cc: Likewise.
+       * testsuite/20_util/optional/constexpr/in_place.cc: Adjust.
+       * testsuite/20_util/optional/in_place.cc: Likewise.
+       * testsuite/20_util/optional/make_optional.cc: Add tests for
+       the new overloads of make_optional.
+
 2016-07-13  Ville Voutilainen  <ville.voutilainen@gmail.com>
 
        Implement P0307R2, Making Optional Greater Equal Again.
index 2e8baa6f8dde134d1f40a035ddd593a335dc7f8e..54882d797e20414655ce3c1c299db73921bbcd9a 100644 (file)
@@ -79,8 +79,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
     // Holds either pointer to a heap object or the contained object itself.
     union _Storage
     {
-      // This constructor intentionally doesn't initialize anything.
-      _Storage() = default;
+      constexpr _Storage() : _M_ptr{nullptr} {}
 
       // Prevent trivial copies of this type, buffer might hold a non-POD.
       _Storage(const _Storage&) = delete;
@@ -113,12 +112,12 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
     // construct/destruct
 
     /// Default constructor, creates an empty object.
-    any() noexcept : _M_manager(nullptr) { }
+    constexpr any() noexcept : _M_manager(nullptr) { }
 
     /// Copy constructor, copies the state of @p __other
     any(const any& __other)
     {
-      if (__other.empty())
+      if (!__other.has_value())
        _M_manager = nullptr;
       else
        {
@@ -131,11 +130,11 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
     /**
      * @brief Move constructor, transfer the state from @p __other
      *
-     * @post @c __other.empty() (this postcondition is a GNU extension)
+     * @post @c !__other.has_value() (this postcondition is a GNU extension)
      */
     any(any&& __other) noexcept
     {
-      if (__other.empty())
+      if (!__other.has_value())
        _M_manager = nullptr;
       else
        {
@@ -145,45 +144,71 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
        }
     }
 
+    template <typename _Tp, typename... _Args>
+    using __any_constructible_t =
+      enable_if_t<__and_<is_copy_constructible<_Tp>,
+                        is_constructible<_Tp, _Args...>>::value,
+                 bool>;
+
     /// 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 = true>
+              __any_constructible_t<_Tp, _ValueType&&> = true>
       any(_ValueType&& __value)
       : _M_manager(&_Mgr::_S_manage)
       {
         _Mgr::_S_create(_M_storage, std::forward<_ValueType>(__value));
-       static_assert(is_copy_constructible<_Tp>::value,
-                     "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>
+              enable_if_t<__and_<is_copy_constructible<_Tp>,
+                                __not_<
+                                  is_constructible<_Tp,
+                                                   _ValueType&&>>>::value,
+                         bool> = 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(); }
+    /// Construct with an object created from @p __args as the contained object.
+    template <typename _Tp, typename... _Args,
+             typename _Mgr = _Manager<_Tp>,
+              __any_constructible_t<_Tp, _Args&&...> = false>
+      any(in_place_type_t<_Tp>, _Args&&... __args)
+      : _M_manager(&_Mgr::_S_manage)
+      {
+        _Mgr::_S_create(_M_storage, std::forward<_Args>(__args)...);
+      }
+
+    /// Construct with an object created from @p __il and @p __args as
+    /// the contained object.
+    template <typename _Tp, typename _Up, typename... _Args,
+             typename _Mgr = _Manager<_Tp>,
+              __any_constructible_t<_Tp, initializer_list<_Up>,
+                                   _Args&&...> = false>
+      any(in_place_type_t<_Tp>, initializer_list<_Up> __il, _Args&&... __args)
+      : _M_manager(&_Mgr::_S_manage)
+      {
+        _Mgr::_S_create(_M_storage, __il, std::forward<_Args>(__args)...);
+      }
+
+    /// Destructor, calls @c reset()
+    ~any() { reset(); }
 
     // assignments
 
     /// Copy the state of another object.
     any& operator=(const any& __rhs)
     {
-      if (__rhs.empty())
-       clear();
+      if (!__rhs.has_value())
+       reset();
       else if (this != &__rhs)
        {
-         if (!empty())
+         if (has_value())
            _M_manager(_Op_destroy, this, nullptr);
          _Arg __arg;
          __arg._M_any = this;
@@ -195,15 +220,15 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
     /**
      * @brief Move assignment operator
      *
-     * @post @c __rhs.empty() (not guaranteed for other implementations)
+     * @post @c !__rhs.has_value() (not guaranteed for other implementations)
      */
     any& operator=(any&& __rhs) noexcept
     {
-      if (__rhs.empty())
-       clear();
+      if (!__rhs.has_value())
+       reset();
       else if (this != &__rhs)
        {
-         if (!empty())
+         if (has_value())
            _M_manager(_Op_destroy, this, nullptr);
          _Arg __arg;
          __arg._M_any = this;
@@ -214,19 +239,44 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
 
     /// Store a copy of @p __rhs as the contained object.
     template<typename _ValueType>
-      enable_if_t<!is_same<any, decay_t<_ValueType>>::value, any&>
+    enable_if_t<__and_<__not_<is_same<any, decay_t<_ValueType>>>,
+                      is_copy_constructible<_ValueType>>::value, any&>
       operator=(_ValueType&& __rhs)
       {
        *this = any(std::forward<_ValueType>(__rhs));
        return *this;
       }
 
+    /// Emplace with an object created from @p __args as the contained object.
+    template <typename _Tp, typename... _Args,
+             typename _Mgr = _Manager<_Tp>,
+              __any_constructible_t<_Tp, _Args&&...> = false>
+      void emplace(_Args&&... __args)
+      {
+       reset();
+       _M_manager = &_Mgr::_S_manage;
+        _Mgr::_S_create(_M_storage, std::forward<_Args>(__args)...);
+      }
+
+    /// Emplace with an object created from @p __il and @p __args as
+    /// the contained object.
+    template <typename _Tp, typename _Up, typename... _Args,
+             typename _Mgr = _Manager<_Tp>,
+              __any_constructible_t<_Tp, initializer_list<_Up>,
+                                   _Args&&...> = false>
+      void emplace(initializer_list<_Up> __il, _Args&&... __args)
+      {
+       reset();
+       _M_manager = &_Mgr::_S_manage;
+        _Mgr::_S_create(_M_storage, __il, std::forward<_Args>(__args)...);
+      }
+
     // modifiers
 
     /// If not empty, destroy the contained object.
-    void clear() noexcept
+    void reset() noexcept
     {
-      if (!empty())
+      if (has_value())
       {
        _M_manager(_Op_destroy, this, nullptr);
        _M_manager = nullptr;
@@ -236,10 +286,10 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
     /// Exchange state with another object.
     void swap(any& __rhs) noexcept
     {
-      if (empty() && __rhs.empty())
+      if (!has_value() && !__rhs.has_value())
        return;
 
-      if (!empty() && !__rhs.empty())
+      if (has_value() && __rhs.has_value())
        {
          if (this == &__rhs)
            return;
@@ -255,8 +305,8 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
        }
       else
        {
-         any* __empty = empty() ? this : &__rhs;
-         any* __full = empty() ? &__rhs : this;
+         any* __empty = !has_value() ? this : &__rhs;
+         any* __full = !has_value() ? &__rhs : this;
          _Arg __arg;
          __arg._M_any = __empty;
          __full->_M_manager(_Op_xfer, __full, &__arg);
@@ -266,13 +316,13 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
     // observers
 
     /// Reports whether there is a contained object or not.
-    bool empty() const noexcept { return _M_manager == nullptr; }
+    bool has_value() const noexcept { return _M_manager != nullptr; }
 
 #if __cpp_rtti
     /// The @c typeid of the contained object, or @c typeid(void) if empty.
     const type_info& type() const noexcept
     {
-      if (empty())
+      if (!has_value())
        return typeid(void);
       _Arg __arg;
       _M_manager(_Op_get_type_info, this, &__arg);
@@ -316,6 +366,14 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
            void* __addr = &__storage._M_buffer;
            ::new (__addr) _Tp(std::forward<_Up>(__value));
          }
+
+       template<typename... _Args>
+         static void
+         _S_create(_Storage& __storage, _Args&&... __args)
+         {
+           void* __addr = &__storage._M_buffer;
+           ::new (__addr) _Tp(std::forward<_Args>(__args)...);
+         }
       };
 
     // Manage external contained object.
@@ -331,12 +389,32 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
          {
            __storage._M_ptr = new _Tp(std::forward<_Up>(__value));
          }
+       template<typename... _Args>
+         static void
+         _S_create(_Storage& __storage, _Args&&... __args)
+         {
+           __storage._M_ptr = new _Tp(std::forward<_Args>(__args)...);
+         }
       };
   };
 
   /// Exchange the states of two @c any objects.
   inline void swap(any& __x, any& __y) noexcept { __x.swap(__y); }
 
+  /// Create an any holding a @c _Tp constructed from @c __args.
+  template <typename _Tp, typename... _Args>
+    any make_any(_Args&&... __args)
+    {
+      return any(in_place<_Tp>, std::forward<_Args>(__args)...);
+    }
+
+  /// Create an any holding a @c _Tp constructed from @c __il and @c __args.
+  template <typename _Tp, typename _Up, typename... _Args>
+    any make_any(initializer_list<_Up> __il, _Args&&... __args)
+    {
+      return any(in_place<_Tp>, __il, std::forward<_Args>(__args)...);
+    }
+
   /**
    * @brief Access the contained object.
    *
index f1bb17c75dc937442d98d8ec592d9591c891d7a3..2ea4fddb31d7c742d3081c2a4402a72ca0aa1623 100644 (file)
@@ -57,13 +57,6 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
   template<typename _Tp>
     class optional;
 
-  // [X.Y.5]
-  /// Tag type for in-place construction.
-  struct in_place_t { };
-
-  /// Tag for in-place construction.
-  constexpr in_place_t in_place { };
-
   // [X.Y.6]
   /// Tag type to disengage optional objects.
   struct nullopt_t
@@ -91,9 +84,9 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
    */
   class bad_optional_access : public logic_error
   {
+    // XXX See LEWG 72, https://issues.isocpp.org/show_bug.cgi?id=72
   public:
     bad_optional_access() : logic_error("bad optional access") { }
-
     // XXX This constructor is non-standard. Should not be inline
     explicit bad_optional_access(const char* __arg) : logic_error(__arg) { }
 
@@ -641,18 +634,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)
        {
@@ -712,6 +702,9 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
       constexpr explicit operator bool() const noexcept
       { return this->_M_is_engaged(); }
 
+      constexpr bool has_value() const noexcept
+      { return this->_M_is_engaged(); }
+
       constexpr const _Tp&
       value() const&
       {
@@ -777,6 +770,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
            ? std::move(this->_M_get())
            : static_cast<_Tp>(std::forward<_Up>(__u));
        }
+      void reset() { this->_M_reset(); }
     };
 
   template<typename _Tp>
@@ -980,6 +974,16 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
     make_optional(_Tp&& __t)
     { return optional<decay_t<_Tp>> { std::forward<_Tp>(__t) }; }
 
+  template<typename _Tp, typename ..._Args>
+    constexpr optional<_Tp>
+    make_optional(_Args&&... __args)
+    { return optional<_Tp> { in_place, std::forward<_Args>(__args)... }; }
+
+  template<typename _Tp, typename _Up, typename ..._Args>
+    constexpr optional<_Tp>
+    make_optional(initializer_list<_Up> __il, _Args&&... __args)
+    { return optional<_Tp> { in_place, __il, std::forward<_Args>(__args)... }; }
+
   // [X.Y.12]
   template<typename _Tp>
     struct hash<optional<_Tp>>
index 1451a91d42a7a938dad948ed34153c5a4f68629f..106ba4dfcf3bbb3ebfabbb8832c5b2eceae253e2 100644 (file)
 #include <bits/move.h>
 #include <initializer_list>
 
+#if __cplusplus > 201402L
+#include <exception>
+#endif
+
 namespace std _GLIBCXX_VISIBILITY(default)
 {
 _GLIBCXX_BEGIN_NAMESPACE_VERSION
@@ -330,6 +334,30 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
     using index_sequence_for = make_index_sequence<sizeof...(_Types)>;
 #endif
 
+#if __cplusplus > 201402L
+
+  struct in_place_tag {
+    in_place_tag() = delete;
+  };
+
+  struct __in_place;
+  template<typename _Tp> struct __in_place_type;
+  template<size_t _Idx> struct __in_place_index;
+
+  using in_place_t = in_place_tag(&)(__in_place*);
+  template <class _Tp>
+    using in_place_type_t = in_place_tag(&)(__in_place_type<_Tp>*);
+  template <int _Idx>
+    using in_place_index_t = in_place_tag(&)(__in_place_index<_Idx>*);
+
+  inline in_place_tag in_place(__in_place*) {terminate();}
+  template <class _Tp>
+    in_place_tag in_place(__in_place_type<_Tp>*) {terminate();}
+  template <size_t _Idx>
+    in_place_tag in_place(__in_place_index<_Idx>*) {terminate();}
+
+#endif
+
 _GLIBCXX_END_NAMESPACE_VERSION
 } // namespace
 
index 582a92d2f07f066856bab5d42d4bd1be2a5951c8..5e3ffa70ce6b4a54beaacb865efdf51209238617 100644 (file)
@@ -28,12 +28,12 @@ void test01()
   any x;
   any y;
   y = x;
-  VERIFY( x.empty() );
-  VERIFY( y.empty() );
+  VERIFY( !x.has_value() );
+  VERIFY( !y.has_value() );
 
   y = std::move(x);
-  VERIFY( x.empty() );
-  VERIFY( y.empty() );
+  VERIFY( !x.has_value() );
+  VERIFY( !y.has_value() );
 }
 
 void test02()
@@ -41,16 +41,16 @@ void test02()
   any x(1);
   any y;
   y = x;
-  VERIFY( !x.empty() );
-  VERIFY( !y.empty() );
+  VERIFY( x.has_value() );
+  VERIFY( y.has_value() );
 
   x = std::move(y);
-  VERIFY( !x.empty() );
-  VERIFY( y.empty() );
+  VERIFY( x.has_value() );
+  VERIFY( !y.has_value() );
 
   x = y;
-  VERIFY( x.empty() );
-  VERIFY( y.empty() );
+  VERIFY( !x.has_value() );
+  VERIFY( !y.has_value() );
 }
 
 int main()
diff --git a/libstdc++-v3/testsuite/20_util/any/assign/emplace.cc b/libstdc++-v3/testsuite/20_util/any/assign/emplace.cc
new file mode 100644 (file)
index 0000000..663bae2
--- /dev/null
@@ -0,0 +1,62 @@
+// { dg-options "-std=gnu++17" }
+// { dg-do run }
+
+// 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 <any>
+#include <testsuite_hooks.h>
+#include <vector>
+#include <tuple>
+
+struct combined {
+  std::vector<int> v;
+  std::tuple<int, int> t;
+  template<class... Args>
+  combined(std::initializer_list<int> il, Args&&... args)
+    : v(il), t(std::forward<Args>(args)...)
+  {
+  }
+};
+
+int main()
+{
+  const int i = 42;
+  std::any o;
+  o.emplace<int>(i);
+  int& i2 = std::any_cast<int&>(o);
+  VERIFY( i2 == 42 );
+  VERIFY( &i2 != &i );
+  std::any o2;
+  o2.emplace<std::tuple<int, int>>(1, 2);
+  std::tuple<int, int>& t = std::any_cast<std::tuple<int, int>&>(o2);
+  VERIFY( std::get<0>(t) == 1 && std::get<1>(t) == 2);
+  std::any o3;
+  o3.emplace<std::vector<int>>({42, 666});
+  std::vector<int>& v = std::any_cast<std::vector<int>&>(o3);
+  VERIFY(v[0] == 42 && v[1] == 666);
+  std::any o4;
+  o4.emplace<combined>({42, 666});
+  combined& c = std::any_cast<combined&>(o4);
+  VERIFY(c.v[0] == 42 && c.v[1] == 666
+        && std::get<0>(c.t) == 0 && std::get<1>(c.t) == 0 );
+  std::any o5;
+  o5.emplace<combined>({1, 2}, 3, 4);
+  combined& c2 = std::any_cast<combined&>(o5);
+  VERIFY(c2.v[0] == 1 && c2.v[1] == 2
+        && std::get<0>(c2.t) == 3 && std::get<1>(c2.t) == 4 );
+}
index e773efad11c36a6c145fb508909562ac50e601c2..f0bf12838c7cd6c7c9640930ae667ffa425fd5b4 100644 (file)
@@ -36,13 +36,13 @@ test01()
 
   any a;
   a = a;
-  VERIFY( a.empty() );
+  VERIFY( !a.has_value() );
 
   a = A{};
   a = a;
-  VERIFY( !a.empty() );
+  VERIFY( a.has_value() );
 
-  a.clear();
+  a.reset();
   VERIFY( live_objects.empty() );
 }
 
@@ -57,13 +57,13 @@ test02()
 
   X x;
   std::swap(x, x); // results in "self-move-assignment" of X::a
-  VERIFY( x.a.empty() );
+  VERIFY( !x.a.has_value() );
 
   x.a = A{};
   std::swap(x, x); // results in "self-move-assignment" of X::a
-  VERIFY( !x.a.empty() );
+  VERIFY( x.a.has_value() );
 
-  x.a.clear();
+  x.a.reset();
   VERIFY( live_objects.empty() );
 }
 
@@ -74,13 +74,13 @@ test03()
 
   any a;
   a.swap(a);
-  VERIFY( a.empty() );
+  VERIFY( !a.has_value() );
 
   a = A{};
   a.swap(a);
-  VERIFY( !a.empty() );
+  VERIFY( a.has_value() );
 
-  a.clear();
+  a.reset();
   VERIFY( live_objects.empty() );
 }
 
index d66320413d4f8845628ffaba85184e3bc50e3aed..59af878a60c19d5e051845ea840c78d99b2dab43 100644 (file)
@@ -26,29 +26,29 @@ using std::any;
 void test01()
 {
   any x;
-  VERIFY( x.empty() );
+  VERIFY( !x.has_value() );
 
   any y(x);
-  VERIFY( x.empty() );
-  VERIFY( y.empty() );
+  VERIFY( !x.has_value() );
+  VERIFY( !y.has_value() );
 
   any z(std::move(y));
-  VERIFY( y.empty() );
-  VERIFY( z.empty() );
+  VERIFY( !y.has_value() );
+  VERIFY( !z.has_value() );
 }
 
 void test02()
 {
   any x(1);
-  VERIFY( !x.empty() );
+  VERIFY( x.has_value() );
 
   any y(x);
-  VERIFY( !x.empty() );
-  VERIFY( !y.empty() );
+  VERIFY( x.has_value() );
+  VERIFY( y.has_value() );
 
   any z(std::move(y));
-  VERIFY( y.empty() );
-  VERIFY( !z.empty() );
+  VERIFY( !y.has_value() );
+  VERIFY( z.has_value() );
 }
 
 int main()
diff --git a/libstdc++-v3/testsuite/20_util/any/cons/in_place.cc b/libstdc++-v3/testsuite/20_util/any/cons/in_place.cc
new file mode 100644 (file)
index 0000000..2368b83
--- /dev/null
@@ -0,0 +1,57 @@
+// { dg-options "-std=gnu++17" }
+// { dg-do run }
+
+// 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 <any>
+#include <testsuite_hooks.h>
+#include <vector>
+#include <tuple>
+
+struct combined {
+  std::vector<int> v;
+  std::tuple<int, int> t;
+  template<class... Args>
+  combined(std::initializer_list<int> il, Args&&... args)
+    : v(il), t(std::forward<Args>(args)...)
+  {
+  }
+};
+
+int main()
+{
+  const int i = 42;
+  std::any o(std::in_place<int>, i);
+  int& i2 = std::any_cast<int&>(o);
+  VERIFY( i2 == 42 );
+  VERIFY( &i2 != &i );
+  std::any o2(std::in_place<std::tuple<int, int>>, 1, 2);
+  std::tuple<int, int>& t = std::any_cast<std::tuple<int, int>&>(o2);
+  VERIFY( std::get<0>(t) == 1 && std::get<1>(t) == 2);
+  std::any o3(std::in_place<std::vector<int>>, {42, 666});
+  std::vector<int>& v = std::any_cast<std::vector<int>&>(o3);
+  VERIFY(v[0] == 42 && v[1] == 666);
+  std::any o4(std::in_place<combined>, {42, 666});
+  combined& c = std::any_cast<combined&>(o4);
+  VERIFY(c.v[0] == 42 && c.v[1] == 666
+        && std::get<0>(c.t) == 0 && std::get<1>(c.t) == 0 );
+  std::any o5(std::in_place<combined>, {1, 2}, 3, 4);
+  combined& c2 = std::any_cast<combined&>(o5);
+  VERIFY(c2.v[0] == 1 && c2.v[1] == 2
+        && std::get<0>(c2.t) == 3 && std::get<1>(c2.t) == 4 );
+}
diff --git a/libstdc++-v3/testsuite/20_util/any/make_any.cc b/libstdc++-v3/testsuite/20_util/any/make_any.cc
new file mode 100644 (file)
index 0000000..4ec245b
--- /dev/null
@@ -0,0 +1,57 @@
+// { dg-options "-std=gnu++17" }
+// { dg-do run }
+
+// 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 <any>
+#include <testsuite_hooks.h>
+#include <vector>
+#include <tuple>
+
+struct combined {
+  std::vector<int> v;
+  std::tuple<int, int> t;
+  template<class... Args>
+  combined(std::initializer_list<int> il, Args&&... args)
+    : v(il), t(std::forward<Args>(args)...)
+  {
+  }
+};
+
+int main()
+{
+  const int i = 42;
+  auto o = std::make_any<int>(i);
+  int& i2 = std::any_cast<int&>(o);
+  VERIFY( i2 == 42 );
+  VERIFY( &i2 != &i );
+  auto o2 = std::make_any<std::tuple<int, int>>(1, 2);
+  std::tuple<int, int>& t = std::any_cast<std::tuple<int, int>&>(o2);
+  VERIFY( std::get<0>(t) == 1 && std::get<1>(t) == 2);
+  auto o3 = std::make_any<std::vector<int>>({42, 666});
+  std::vector<int>& v = std::any_cast<std::vector<int>&>(o3);
+  VERIFY(v[0] == 42 && v[1] == 666);
+  auto o4 = std::make_any<combined>({42, 666});
+  combined& c = std::any_cast<combined&>(o4);
+  VERIFY(c.v[0] == 42 && c.v[1] == 666
+        && std::get<0>(c.t) == 0 && std::get<1>(c.t) == 0 );
+  auto o5 = std::make_any<combined>({1, 2}, 3, 4);
+  combined& c2 = std::any_cast<combined&>(o5);
+  VERIFY(c2.v[0] == 1 && c2.v[1] == 2
+        && std::get<0>(c2.t) == 3 && std::get<1>(c2.t) == 4 );
+}
index 43c6c6b4a26ae91321177425b7840cd3424ede49..32b4e767fd2a7e3250509a88ec59dba95e9e5f83 100644 (file)
@@ -26,5 +26,5 @@ void test01()
   using std::any_cast;
 
   const any y(1);
-  any_cast<int&>(y); // { dg-error "qualifiers" "" { target { *-*-* } } 357 }
+  any_cast<int&>(y); // { dg-error "qualifiers" "" { target { *-*-* } } 435 }
 }
index 0b3e1eb26de3c8c8cac6f31f32a18bb4247b50f4..26a86dd5cfc3877d7e2354f19f42d1c0f58675b4 100644 (file)
@@ -28,8 +28,8 @@ void test01()
   any x(1);
   any y;
   swap(x, y);
-  VERIFY( x.empty() );
-  VERIFY( !y.empty() );
+  VERIFY( !x.has_value() );
+  VERIFY( y.has_value() );
 }
 
 int main()
index 36b9c247843fc7ef22261790fae8e641854172e2..39cbe96fd8d3c01b8bdc0ed55e3353ee5ac8c5ee 100644 (file)
@@ -28,14 +28,14 @@ void test01()
   any x(1);
   any y;
   x.swap(y);
-  VERIFY( x.empty() );
-  VERIFY( !y.empty() );
+  VERIFY( !x.has_value() );
+  VERIFY( y.has_value() );
   x.swap(y);
-  VERIFY( !x.empty() );
-  VERIFY( y.empty() );
+  VERIFY( x.has_value() );
+  VERIFY( !y.has_value() );
 
-  x.clear();
-  VERIFY( x.empty() );
+  x.reset();
+  VERIFY( !x.has_value() );
 }
 
 int main()
diff --git a/libstdc++-v3/testsuite/20_util/any/requirements.cc b/libstdc++-v3/testsuite/20_util/any/requirements.cc
new file mode 100644 (file)
index 0000000..67e4253
--- /dev/null
@@ -0,0 +1,33 @@
+// { dg-options "-std=gnu++17" }
+// { dg-do compile }
+
+// 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 <any>
+#include <testsuite_hooks.h>
+
+#include <memory>
+
+using std::any;
+using std::unique_ptr;
+
+static_assert(std::is_assignable<any&, int>::value);
+static_assert(!std::is_assignable<any&, unique_ptr<int>>::value);
+static_assert(std::is_constructible<any, int>::value);
+static_assert(!std::is_constructible<any, unique_ptr<int>>::value);
+
diff --git a/libstdc++-v3/testsuite/20_util/in_place/requirements.cc b/libstdc++-v3/testsuite/20_util/in_place/requirements.cc
new file mode 100644 (file)
index 0000000..fc141d8
--- /dev/null
@@ -0,0 +1,47 @@
+// { dg-options "-std=gnu++17" }
+// { dg-do compile }
+
+// 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 <utility>
+#include <type_traits>
+#include <testsuite_hooks.h>
+
+using std::in_place_t;
+using std::in_place_type_t;
+using std::in_place_index_t;
+
+float f(in_place_type_t<float>);
+double f(in_place_type_t<double>);
+char f(in_place_index_t<0>);
+unsigned int f(in_place_index_t<1>);
+int f(in_place_t);
+
+static_assert(std::is_same<decltype(f(in_place_t(std::in_place))), int>::value);
+static_assert(std::is_same<decltype(f(std::in_place<float>)), float>::value);
+static_assert(std::is_same<decltype(f(std::in_place<double>)), double>::value);
+static_assert(std::is_same<decltype(f(std::in_place<0>)), char>::value);
+static_assert(std::is_same<decltype(f(std::in_place<1>)), unsigned int>::value);
+
+template <class T, class... Args> float h(in_place_type_t<T>, Args&&...);
+template <size_t N, class... Args> int h(in_place_index_t<N>, Args&&...);
+template <class T> double h(in_place_t, T&&);
+
+static_assert(std::is_same<decltype(h(std::in_place, 1)), double>::value);
+static_assert(std::is_same<decltype(h(std::in_place<float>, 1)), float>::value);
+static_assert(std::is_same<decltype(h(std::in_place<0>, 1)), int>::value);
index cd75275aaff5531c05e63d79e310e99d12127191..6db03ea5138d5e77df6cabc91f5c37a17af14599 100644 (file)
@@ -24,9 +24,6 @@
 int main()
 {
   // [20.5.5] In-place construction
-  static_assert( std::is_same<decltype(std::in_place), const std::in_place_t>(), "" );
-  static_assert( std::is_empty<std::in_place_t>(), "" );
-
   {
     constexpr std::optional<int> o { std::in_place };
     static_assert( o, "" );
index ef8c744f1dccbbbc26e5087bbd942b364be80466..53059dbba7f183d50908ccbe011c74d9af59c43f 100644 (file)
@@ -26,9 +26,6 @@
 int main()
 {
   // [20.5.5] In-place construction
-  static_assert( std::is_same<decltype(std::in_place), const std::in_place_t>(), "" );
-  static_assert( std::is_empty<std::in_place_t>(), "" );
-
   {
     std::optional<int> o { std::in_place };
     VERIFY( o );
index 6f245c716adcf3fabe5295911fa3e1fb21a661da..b288a250bd56e2ca92ba863ac6f638c26a62d6ee 100644 (file)
 
 #include <optional>
 #include <testsuite_hooks.h>
+#include <vector>
+#include <tuple>
+
+struct combined {
+  std::vector<int> v;
+  std::tuple<int, int> t;
+  template<class... Args>
+  combined(std::initializer_list<int> il, Args&&... args)
+    : v(il), t(std::forward<Args>(args)...)
+  {
+  }
+};
 
 int main()
 {
@@ -28,4 +40,22 @@ int main()
   static_assert( std::is_same<decltype(o), std::optional<int>>(), "" );
   VERIFY( o && *o == 42 );
   VERIFY( &*o != &i );
+  auto o2 = std::make_optional<std::tuple<int, int>>(1, 2);
+  static_assert( std::is_same<decltype(o2),
+                std::optional<std::tuple<int, int>>>(), "" );
+  VERIFY( o2 && std::get<0>(*o2) == 1 && std::get<1>(*o2) == 2);
+  auto o3 = std::make_optional<std::vector<int>>({42, 666});
+  static_assert( std::is_same<decltype(o3),
+                std::optional<std::vector<int>>>(), "" );
+  VERIFY(o3 && (*o3)[0] == 42 && (*o3)[1] == 666);
+  auto o4 = std::make_optional<combined>({42, 666});
+  static_assert( std::is_same<decltype(o4),
+                std::optional<combined>>(), "" );
+  VERIFY(o4 && (o4->v)[0] == 42 && (o4->v)[1] == 666
+        && std::get<0>(o4->t) == 0 && std::get<1>(o4->t) == 0 );
+  auto o5 = std::make_optional<combined>({1, 2}, 3, 4);
+  static_assert( std::is_same<decltype(o5),
+                std::optional<combined>>(), "" );
+  VERIFY(o4 && (o5->v)[0] == 1 && (o5->v)[1] == 2
+        && std::get<0>(o5->t) == 3 && std::get<1>(o5->t) == 4 );
 }