This is the mail archive of the libstdc++@gcc.gnu.org mailing list for the libstdc++ project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

[RFC-2] Add C++14's optional type (20.6/n3672).


I've updated optional to use a union instead of std::aligned_storage.
This gets rid of the hack and should work correctly with constexpr.

I've also fixed the operator= issue.  It was actually a bug in the code
(*this = ... vs. **this = ...).

Looking forward to comments.  I've requested assignment papers from the FSF.

Regards,
RÃdiger Sonderfeld

-- 8< ---------------------------------------------------------------- >8 --

* libstdc++-v3/include/Makefile.am (std_headers): Add optional.
* libstdc++-v3/include/std/optional: New header.
* libstdc++-v3/testsuite/20_util/optional/assignment/assignment.cc: New
  test.
* libstdc++-v3/testsuite/20_util/optional/comparison_operators/comparison.cc:
  New test.
* libstdc++-v3/testsuite/20_util/optional/constructors/complexctors.cc:
  New test.
* libstdc++-v3/testsuite/20_util/optional/constructors/ctors.cc: New test.
* libstdc++-v3/testsuite/20_util/optional/hash/hash.cc: New test.
* libstdc++-v3/testsuite/20_util/optional/observers/observers.cc: New test.
* libstdc++-v3/testsuite/20_util/optional/swap/swap.cc: New test.
* libstdc++-v3/include/bits/functexcept.h (_throw_bad_optional_access):
  New function.
* libstdc++-v3/src/c++11/functexcept.cc (_throw_bad_optional_access):
  New function.
---
 libstdc++-v3/include/Makefile.am                   |   1 +
 libstdc++-v3/include/bits/functexcept.h            |   3 +
 libstdc++-v3/include/std/optional                  | 584 +++++++++++++++++++++
 libstdc++-v3/src/c++11/functexcept.cc              |   5 +
 .../20_util/optional/assignment/assignment.cc      |  57 ++
 .../optional/comparison_operators/comparison.cc    |  67 +++
 .../20_util/optional/constructors/complexctors.cc  | 169 ++++++
 .../20_util/optional/constructors/ctors.cc         |  78 +++
 .../testsuite/20_util/optional/hash/hash.cc        |  57 ++
 .../20_util/optional/observers/observers.cc        | 111 ++++
 .../testsuite/20_util/optional/swap/swap.cc        |  77 +++
 11 files changed, 1209 insertions(+)
 create mode 100644 libstdc++-v3/include/std/optional
 create mode 100644 libstdc++-v3/testsuite/20_util/optional/assignment/assignment.cc
 create mode 100644 libstdc++-v3/testsuite/20_util/optional/comparison_operators/comparison.cc
 create mode 100644 libstdc++-v3/testsuite/20_util/optional/constructors/complexctors.cc
 create mode 100644 libstdc++-v3/testsuite/20_util/optional/constructors/ctors.cc
 create mode 100644 libstdc++-v3/testsuite/20_util/optional/hash/hash.cc
 create mode 100644 libstdc++-v3/testsuite/20_util/optional/observers/observers.cc
 create mode 100644 libstdc++-v3/testsuite/20_util/optional/swap/swap.cc

diff --git a/libstdc++-v3/include/Makefile.am b/libstdc++-v3/include/Makefile.am
index 3be6e57..c10e882 100644
--- a/libstdc++-v3/include/Makefile.am
+++ b/libstdc++-v3/include/Makefile.am
@@ -51,6 +51,7 @@ std_headers = \
 	${std_srcdir}/memory \
 	${std_srcdir}/mutex \
 	${std_srcdir}/numeric \
+	${std_srcdir}/optional \
 	${std_srcdir}/ostream \
 	${std_srcdir}/queue \
 	${std_srcdir}/random \
diff --git a/libstdc++-v3/include/bits/functexcept.h b/libstdc++-v3/include/bits/functexcept.h
index 03e2040..370e0e6 100644
--- a/libstdc++-v3/include/bits/functexcept.h
+++ b/libstdc++-v3/include/bits/functexcept.h
@@ -104,6 +104,9 @@ namespace std _GLIBCXX_VISIBILITY(default)
   void
   __throw_bad_function_call() __attribute__((__noreturn__));
 
+  // Helpers for exception objects in <optional>
+  void
+  __throw_bad_optional_access(const char*) __attribute__((__noreturn__));
 _GLIBCXX_END_NAMESPACE_VERSION
 } // namespace
 
diff --git a/libstdc++-v3/include/std/optional b/libstdc++-v3/include/std/optional
new file mode 100644
index 0000000..2fed7ca
--- /dev/null
+++ b/libstdc++-v3/include/std/optional
@@ -0,0 +1,584 @@
+// <optional> -*- C++ -*-
+
+// Copyright (C) 2013 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.
+
+// Under Section 7 of GPL version 3, you are granted additional
+// permissions described in the GCC Runtime Library Exception, version
+// 3.1, as published by the Free Software Foundation.
+
+// You should have received a copy of the GNU General Public License and
+// a copy of the GCC Runtime Library Exception along with this program;
+// see the files COPYING3 and COPYING.RUNTIME respectively.  If not, see
+// <http://www.gnu.org/licenses/>.
+
+/** @file include/optional
+ *  This is a Standard C++ Library header.
+ */
+
+#ifndef _GLIBCXX_OPTIONAL
+#define _GLIBCXX_OPTIONAL 1
+
+#pragma GCC system_header
+
+#include <bits/c++14_warning.h>
+#include <bits/c++config.h>
+
+#include <stdexcept>
+#include <type_traits>
+
+#include <initializer_list>
+
+namespace std _GLIBCXX_VISIBILITY(default)
+{
+_GLIBCXX_BEGIN_NAMESPACE_VERSION
+
+  // 20.5.4, optional for object types
+  template<typename _Tp>
+    class optional;
+
+  // 20.5.5, In-place construction
+  struct in_place_t
+  { };
+  constexpr in_place_t in_place{};
+
+  // 20.5.6, Disengaged state indicator
+  struct nullopt_t
+  {
+    explicit constexpr nullopt_t(int) { }
+  };
+  constexpr nullopt_t nullopt{0};
+
+  // 20.5.7, class bad_optional_access
+  class bad_optional_access : public logic_error
+  {
+
+  public:
+    explicit
+    bad_optional_access(const string& __what_arg)
+      : logic_error(__what_arg)
+    { }
+
+    explicit bad_optional_access(const char* __what_arg)
+      : logic_error(__what_arg)
+    { }
+  };
+
+  // 20.5.8, Relational operators
+  template<typename _Tp>
+    constexpr bool
+    operator==(const optional<_Tp>& __l, const optional<_Tp>& __r)
+    {
+      return bool(__l) != bool(__r) ? false : bool(__l) == false ? true : *__l == *__r;
+    }
+
+  template<typename _Tp>
+    constexpr bool
+    operator<(const optional<_Tp>& __l, const optional<_Tp>& __r)
+    {
+      return not __l ? false : (not __r ? true : less<_Tp>{}(*__l, *__r));
+    }
+
+  // 20.5.9, Comparison with nullopt
+  template<typename _Tp>
+    constexpr bool
+    operator==(const optional<_Tp>& __o, nullopt_t) noexcept
+    { return not __o; }
+
+  template<typename _Tp>
+    constexpr bool
+    operator==(nullopt_t, const optional<_Tp>& __o) noexcept
+    { return not __o; }
+
+  template<typename _Tp>
+    constexpr bool
+    operator<(const optional<_Tp>&, nullopt_t) noexcept
+    { return false; }
+
+  template<typename _Tp>
+    constexpr bool
+    operator<(nullopt_t, const optional<_Tp> &__o) noexcept
+    { return __o; }
+
+  // 20.5.10, Comparison with T
+  template<typename _Tp>
+    constexpr bool
+    operator==(const optional<_Tp>& __l, const _Tp& __r)
+    { return bool(__l) ? *__l == __r : false; }
+
+  template<typename _Tp>
+    constexpr bool
+    operator==(const _Tp& __l, const optional<_Tp>& __r)
+    { return bool(__r) ? __l == *__r : false; }
+
+  template<typename _Tp>
+    constexpr bool
+    operator<(const optional<_Tp>& __l, const _Tp& __r)
+    { return bool(__l) ? less<_Tp>{}(*__l, __r) : true; }
+
+  template<typename _Tp>
+    constexpr bool
+    operator<(const _Tp& __l, const optional<_Tp>& __r)
+    { return bool(__r) ? less<_Tp>{}(__l, *__r) : true; }
+
+  // 20.5.11, Specialized algorithms
+  template<typename _Tp>
+    void
+    swap(optional<_Tp>& __l, optional<_Tp>& __r)
+      noexcept(noexcept(__l.swap(__r)))
+    {
+      __l.swap(__r);
+    }
+
+  template<typename _Tp>
+    constexpr optional<typename decay<_Tp>::type>
+    make_optional(_Tp&& __t)
+    {
+      return optional<typename decay<_Tp>::type>(std::forward<_Tp>(__t));
+    }
+
+  // 20.5.12, hash support
+  template<typename _Tp>
+    struct hash;
+
+  template<typename _Tp>
+    struct hash<optional<_Tp>>
+    {
+      typedef size_t result_type;
+      typedef optional<_Tp> argument_type;
+
+      result_type
+      operator()(argument_type const& __o) const noexcept
+      {
+        if (__o)
+          return hash<_Tp>{}(*__o);
+        else
+          return 0;
+      }
+    };
+
+  template<typename _Tp>
+    struct _Optional_storage
+    {
+      typedef _Tp value_type;
+
+      bool _M_is_initialized = false;
+
+      union {
+        unsigned char _M_empty;
+        value_type _M_value;
+      };
+
+      constexpr
+      _Optional_storage()
+        : _M_is_initialized(false),
+          _M_empty(0)
+      { }
+
+      _Optional_storage(_Optional_storage const& __obj)
+        : _M_is_initialized(__obj._M_is_initialized)
+      {
+        if(_M_is_initialized)
+          new(addressof(_M_value)) value_type(__obj._M_value);
+      }
+
+      _Optional_storage(_Optional_storage&& __obj)
+        noexcept(is_nothrow_move_constructible<value_type>::value)
+        : _M_is_initialized(__obj._M_is_initialized)
+      {
+        if(_M_is_initialized)
+          new(addressof(_M_value)) value_type(move(__obj._M_value));
+      }
+
+      constexpr
+      _Optional_storage(const value_type& __obj)
+        : _M_is_initialized(true),
+          _M_value(__obj)
+      { }
+
+      constexpr
+      _Optional_storage(value_type&& __obj)
+        : _M_is_initialized(true),
+          _M_value(move(__obj))
+      { }
+
+      template<typename... Args>
+        constexpr explicit
+        _Optional_storage(in_place_t, Args&&... __args)
+          : _M_is_initialized(true),
+            _M_value(forward<Args>(__args)...)
+        { }
+
+      template<typename _Up, typename... Args>
+        constexpr explicit
+        _Optional_storage(in_place_t, initializer_list<_Up> __il, Args&&... __args)
+          : _M_is_initialized(true),
+            _M_value(__il, forward<Args>(__args)...)
+        { }
+
+      ~_Optional_storage() { }
+    };
+
+  template<typename _Tp, bool _Trivial = is_trivially_destructible<_Tp>::value>
+    struct _Optional_base : _Optional_storage<_Tp>
+    {
+      typedef _Optional_storage<_Tp> __storage;
+      using __storage::_M_is_initialized;
+      using __storage::_M_value;
+      typedef _Tp value_type;
+
+      constexpr
+      _Optional_base() = default;
+
+      constexpr
+      _Optional_base(const value_type& __obj)
+        : __storage(__obj)
+      { }
+
+      constexpr
+      _Optional_base(value_type&& __obj)
+        : __storage(move(__obj))
+      { }
+
+      template<typename... Args>
+        constexpr explicit
+        _Optional_base(in_place_t __x, Args&&... __args)
+          : __storage(__x, forward<Args>(__args)...)
+        { }
+
+      template<typename _Up, typename... Args>
+        constexpr explicit
+        _Optional_base(in_place_t __x, initializer_list<_Up> __il, Args&&... __args)
+          : __storage(__x, __il, forward<Args>(__args)...)
+        { }
+
+      void
+      _M_destruct()
+      { }
+
+      void
+      _M_deinit()
+      {
+        _M_is_initialized = false;
+      }
+    };
+
+  template<typename _Tp>
+    struct _Optional_base<_Tp, false> : _Optional_storage<_Tp>
+    {
+      typedef _Optional_storage<_Tp> __storage;
+      using __storage::_M_is_initialized;
+      using __storage::_M_value;
+      typedef _Tp value_type;
+
+      constexpr
+      _Optional_base() = default;
+
+      constexpr
+      _Optional_base(const value_type& __obj)
+        : __storage(__obj)
+      { }
+
+      constexpr
+      _Optional_base(value_type&& __obj)
+        : __storage(move(__obj))
+      { }
+
+      template<typename... Args>
+        constexpr explicit
+        _Optional_base(in_place_t __x, Args&&... __args)
+          : __storage(__x, forward<Args>(__args)...)
+        { }
+
+      template<typename _Up, typename... Args>
+        constexpr explicit
+        _Optional_base(in_place_t __x, initializer_list<_Up> __il, Args&&... __args)
+          : __storage(__x, __il, forward<Args>(__args)...)
+        { }
+
+      void
+      _M_destruct()
+      {
+        _M_value.~_Tp();
+      }
+
+      void
+      _M_deinit()
+      {
+        _M_is_initialized = false;
+        _M_destruct();
+      }
+
+      ~_Optional_base()
+      { _M_destruct(); }
+    };
+
+  template<typename _Tp>
+    class optional : _Optional_base<_Tp>
+    {
+      typedef _Optional_base<_Tp> __base;
+
+      using __base::_M_is_initialized;
+      using __base::_M_value;
+      using __base::_M_deinit;
+      using __base::_M_destruct;
+
+    public:
+      typedef _Tp value_type;
+
+      // 20.5.4.1, constructors
+      constexpr
+      optional() noexcept
+      { }
+
+      constexpr
+      optional(nullopt_t) noexcept
+      { }
+
+      optional(optional const& __obj)
+        : __base(__obj)
+      {
+        static_assert(is_copy_constructible<value_type>::value,
+                      "Requires copy constructible value type");
+      }
+
+      optional(optional&& __obj) noexcept(is_nothrow_move_constructible<value_type>::value)
+        : __base(__obj)
+      {
+        static_assert(is_move_constructible<value_type>::value,
+                      "Requires move constructible value type");
+      }
+
+      constexpr
+      optional(const value_type &__obj)
+        : __base(__obj)
+      {
+        static_assert(is_copy_constructible<value_type>::value,
+                      "Requires copy constructible value type");
+      }
+
+      constexpr
+      optional(value_type&& __obj)
+        : __base(move(__obj))
+      {
+        static_assert(is_move_constructible<value_type>::value,
+                      "Requires move constructible value type");
+      }
+
+      template<typename... Args>
+        constexpr explicit
+        optional(in_place_t __x, Args&&... __args)
+          : __base(__x, forward<Args>(__args)...)
+        {
+          static_assert(is_constructible<value_type, Args&&...>::value,
+                        "Requires constructible value type");
+        }
+
+      template<typename _Up, typename... Args>
+        constexpr explicit
+        optional(in_place_t __x, initializer_list<_Up> __il, Args&&... __args)
+          : __base(__x, __il, forward<Args>(__args)...)
+        {
+          static_assert(is_constructible<value_type, initializer_list<_Up>&, Args&&...>::value,
+                        "Requires constructible value type");
+        }
+
+      // 20.5.4.2, destructor
+      // ~optional() { }
+
+      // 20.5.4.3, assignment
+      optional&
+      operator=(nullopt_t) noexcept
+      {
+        if (_M_is_initialized)
+          _M_deinit();
+        return *this;
+      }
+
+      optional&
+      operator=(const optional& __o)
+      {
+        if (_M_is_initialized)
+          {
+            if (not __o)
+              _M_deinit();
+            else
+              _M_value = *__o;
+          }
+        else if (__o)
+          {
+            _M_is_initialized = true;
+            new(addressof(_M_value)) value_type(*__o);
+          }
+        return *this;
+      }
+
+      optional&
+      operator=(optional&& __o)
+        noexcept(is_nothrow_move_assignable<value_type>::value and
+                 is_nothrow_move_constructible<value_type>::value)
+      {
+        if (_M_is_initialized)
+          {
+            if (not __o)
+              _M_deinit();
+            else
+              _M_value = std::move(*__o);
+          }
+        else if (__o)
+          {
+            _M_is_initialized = true;
+            new(addressof(_M_value)) value_type(std::move(*__o));
+          }
+        return *this;
+      }
+
+      template<typename _Up,
+                typename = typename enable_if<
+                  is_same<typename remove_reference<_Up>::type, _Tp>::value
+                  >::type
+                >
+        optional&
+        operator=(_Up&& __u)
+        {
+          static_assert(is_constructible<_Tp, _Up>::value and is_assignable<_Up, _Tp>::value,
+                        "optional::operator= requirements not meet");
+
+          if (_M_is_initialized)
+            _M_value = std::forward<_Up>(__u);
+          else
+            {
+              _M_is_initialized = true;
+              new(addressof(_M_value)) value_type(std::forward<_Up>(__u));
+            }
+          return *this;
+        }
+
+      template<typename... _Args>
+        void
+        emplace(_Args&&... __args)
+        {
+          *this = nullopt;
+          _M_is_initialized = true;
+          new(addressof(_M_value)) value_type(std::forward<_Args>(__args)...);
+        }
+
+      template<typename _Up, typename... _Args>
+        void
+        emplace(initializer_list<_Up> _il, _Args&&... __args)
+        {
+          *this = nullopt;
+          _M_is_initialized = true;
+          new(addressof(_M_value)) value_type(_il, std::forward<_Args>(__args)...);
+        }
+
+      // 20.5.4.4, swap
+      void
+      swap(optional& __o)
+        noexcept(is_nothrow_move_constructible<_Tp>::value and
+                 noexcept(swap(declval<_Tp&>(), declval<_Tp&>())))
+      {
+        static_assert(is_move_constructible<_Tp>::value,
+                      "optional::swap requires move constructible value type.");
+        if (_M_is_initialized)
+          {
+            if (not __o)
+              {
+                new(addressof(__o._M_value)) value_type(std::move(_M_value));
+                _M_destruct();
+                std::swap(_M_is_initialized, __o._M_is_initialized);
+              }
+            else
+              std::swap(_M_value, *__o);
+          }
+        else
+          {
+            new(addressof(_M_value)) value_type(std::move(*__o));
+            _M_destruct();
+            std::swap(_M_is_initialized, __o._M_is_initialized);
+          }
+      }
+
+      // 20.5.4.5, observers
+      constexpr value_type const*
+      operator->() const
+      {
+        return addressof(_M_value);
+      }
+
+      value_type*
+      operator->()
+      {
+        return addressof(_M_value);
+      }
+
+      constexpr value_type const&
+      operator*() const
+      {
+        return _M_value;
+      }
+
+      value_type&
+      operator*()
+      {
+        return _M_value;
+      }
+
+      constexpr explicit
+      operator bool() const noexcept
+      {
+        return _M_is_initialized;
+      }
+
+      /*constexpr*/ // TODO requires GCC to implement N3652
+      value_type const&
+      value() const
+      {
+        if (not *this)
+          __throw_bad_optional_access("optional::value: bad optional access");
+        return _M_value;
+      }
+
+      value_type&
+      value()
+      {
+        if (not *this)
+          __throw_bad_optional_access("optional::value: bad optional access");
+        return _M_value;
+      }
+
+      template<typename _Up>
+        constexpr value_type
+        value_or(_Up&& __v) const&
+        {
+          static_assert(is_copy_constructible<_Tp>::value and
+                        is_convertible<_Up&&, _Tp>::value,
+                        "Requirements for optional<T>::value_or not met.");
+          return bool(*this) ? **this : static_cast<_Tp>(std::forward<_Up>(__v));
+        }
+
+      template<typename _Up>
+        value_type
+        value_or(_Up&& __v) &&
+        {
+          static_assert(is_move_constructible<_Tp>::value and
+                        is_convertible<_Up&&, _Tp>::value,
+                        "Requirements for optional<T>::value_or not met.");
+          return bool(*this) ? std::move(**this) : static_cast<_Tp>(std::forward<_Up>(__v));
+        }
+    };
+
+_GLIBCXX_END_NAMESPACE_VERSION
+} // namespace std
+
+#endif // _GLIBCXX_OPTIONAL
diff --git a/libstdc++-v3/src/c++11/functexcept.cc b/libstdc++-v3/src/c++11/functexcept.cc
index b18f8ad..450cb59 100644
--- a/libstdc++-v3/src/c++11/functexcept.cc
+++ b/libstdc++-v3/src/c++11/functexcept.cc
@@ -30,6 +30,7 @@
 #include <system_error>
 #include <future>
 #include <functional>
+#include <optional>
 #include <bits/regex_error.h>
 #include <stdarg.h>
 
@@ -136,6 +137,10 @@ namespace std _GLIBCXX_VISIBILITY(default)
   { _GLIBCXX_THROW_OR_ABORT(bad_function_call()); }
 
   void
+  __throw_bad_optional_access(const char* __s __attribute__((unused)))
+  { _GLIBCXX_THROW_OR_ABORT(bad_optional_access(_(__s))); }
+
+  void
   __throw_regex_error(regex_constants::error_type __ecode
 		      __attribute__((unused)))
   { _GLIBCXX_THROW_OR_ABORT(regex_error(__ecode)); }
diff --git a/libstdc++-v3/testsuite/20_util/optional/assignment/assignment.cc b/libstdc++-v3/testsuite/20_util/optional/assignment/assignment.cc
new file mode 100644
index 0000000..c8e6e07
--- /dev/null
+++ b/libstdc++-v3/testsuite/20_util/optional/assignment/assignment.cc
@@ -0,0 +1,57 @@
+// { dg-options "-std=gnu++1y" }
+//
+// Copyright (C) 2013 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 copy of the GNU General Public License along
+// with this library; see the file COPYING3.  If not see
+// <http://www.gnu.org/licenses/>.
+
+#include <optional>
+#include <testsuite_hooks.h>
+
+using std::optional;
+using std::nullopt;
+
+void
+test01()
+{
+  optional<unsigned> a;
+  VERIFY(not a);
+
+  optional<unsigned> b{0xffu};
+  VERIFY(b);
+  VERIFY(b == 0xffu);
+
+  a = b;
+  VERIFY(a);
+  VERIFY(a == 0xffu);
+  VERIFY(b);
+  VERIFY(b == 0xffu);
+
+  a = nullopt;
+  VERIFY(not a);
+  VERIFY(b);
+  VERIFY(b == 0xffu);
+
+  a.emplace(12u);
+  VERIFY(a);
+  VERIFY(a == 12u);
+}
+
+int
+main()
+{
+  test01();
+  return 0;
+}
diff --git a/libstdc++-v3/testsuite/20_util/optional/comparison_operators/comparison.cc b/libstdc++-v3/testsuite/20_util/optional/comparison_operators/comparison.cc
new file mode 100644
index 0000000..f0d8983
--- /dev/null
+++ b/libstdc++-v3/testsuite/20_util/optional/comparison_operators/comparison.cc
@@ -0,0 +1,67 @@
+// { dg-options "-std=gnu++1y" }
+//
+// Copyright (C) 2013 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 copy of the GNU General Public License along
+// with this library; see the file COPYING3.  If not see
+// <http://www.gnu.org/licenses/>.
+
+#include <optional>
+#include <testsuite_hooks.h>
+
+using std::optional;
+using std::nullopt;
+
+void
+test01()
+{
+  optional<unsigned> o0{0u};
+  optional<unsigned> o1{1u};
+  optional<unsigned> oN{nullopt};
+
+  VERIFY( not (oN < o0) );
+  VERIFY( o0 < oN );
+  VERIFY( o0 < o1 );
+  VERIFY( not (oN < oN) );
+  VERIFY( not (o1 < o1) );
+
+  VERIFY( not (oN == o0) );
+  VERIFY( not (o0 == o1) );
+  VERIFY( not (o1 == oN) );
+  VERIFY( oN == oN );
+  VERIFY( o0 == o0 );
+  VERIFY( o1 == o1 );
+
+  VERIFY( oN == nullopt );
+  VERIFY( not (o0 == nullopt) );
+  VERIFY( not (oN == 1u) );
+  VERIFY( o1 == 1u );
+  VERIFY( 1u == o1 );
+  VERIFY( o0 == 0u );
+
+  VERIFY( oN <  1u );
+  VERIFY( not (o0 < nullopt) );
+  VERIFY( o1 <  2u );
+  VERIFY( o0 < o1 );
+  VERIFY( o0 <  1u );
+  VERIFY( not ( o1 < o0 ) );
+  VERIFY( not ( o1 < 1u) );
+}
+
+int
+main()
+{
+  test01();
+  return 0;
+}
diff --git a/libstdc++-v3/testsuite/20_util/optional/constructors/complexctors.cc b/libstdc++-v3/testsuite/20_util/optional/constructors/complexctors.cc
new file mode 100644
index 0000000..8cd2b3e
--- /dev/null
+++ b/libstdc++-v3/testsuite/20_util/optional/constructors/complexctors.cc
@@ -0,0 +1,169 @@
+// { dg-options "-std=gnu++1y" }
+//
+// Copyright (C) 2013 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 copy of the GNU General Public License along
+// with this library; see the file COPYING3.  If not see
+// <http://www.gnu.org/licenses/>.
+
+#include <optional>
+#include <testsuite_hooks.h>
+
+using std::optional;
+using std::nullopt;
+
+struct Test {
+  static unsigned ctor;
+  static unsigned ctor1;
+  static unsigned ctor2;
+  static unsigned copy;
+  static unsigned assign;
+  static unsigned rassign;
+  static unsigned moved;
+  static unsigned dtor;
+
+  static unsigned
+  ctors()
+  {
+    return ctor + copy + ctor1 + ctor2;
+  }
+
+  static void
+  check()
+  {
+    VERIFY(dtor == ctors());
+  }
+
+  static void
+  reset()
+  {
+    ctor = 0;
+    ctor1 = 0;
+    ctor2 = 0;
+    copy = 0;
+    assign = 0;
+    rassign = 0;
+    moved = 0;
+    dtor = 0;
+  }
+
+  int a = 0;
+  int b = 0;
+
+  Test()
+  { ++ctor; };
+
+  Test(int i)
+    : a(i)
+  { ++ctor1; }
+
+  explicit Test(int i, int j)
+    : a(i), b(j)
+  { ++ctor2; }
+
+  Test(Test const&)
+  { ++copy; }
+
+  Test(Test &&)
+  { ++moved; }
+
+  Test&
+  operator=(Test const &)
+  {
+    ++assign;
+    return *this;
+  }
+
+  Test&
+  operator=(Test &&)
+  {
+    ++rassign;
+    return *this;
+  }
+
+  ~Test()
+  { ++dtor; }
+};
+
+unsigned Test::ctor = 0;
+unsigned Test::ctor1 = 0;
+unsigned Test::ctor2 = 0;
+unsigned Test::copy = 0;
+unsigned Test::assign = 0;
+unsigned Test::rassign = 0;
+unsigned Test::moved = 0;
+unsigned Test::dtor = 0;
+
+void test01()
+{
+  Test::reset();
+
+  optional<Test> a;
+  VERIFY( Test::ctors() == 0 );
+  VERIFY( not a);
+  VERIFY( a == nullopt );
+  Test::reset();
+
+  Test t;
+  VERIFY( Test::ctors() == 1 );
+  optional<Test> b{t};
+  VERIFY( Test::ctors() == 2 and Test::ctor == 1 and Test::copy == 1);
+  Test::reset();
+
+  optional<Test> c{1};
+  VERIFY( Test::ctors() == 1 and Test::ctor1 == 1);
+  Test::reset();
+
+  optional<Test> a_c{a};
+  VERIFY( Test::ctors() == 0 );
+  VERIFY( not a_c);
+  VERIFY( a_c == nullopt );
+  Test::reset();
+
+  optional<Test> a_m{std::move(a)};
+  VERIFY( Test::ctors() == 0 );
+  VERIFY( not a_m);
+  VERIFY( a_m == nullopt );
+  Test::reset();
+
+  optional<Test> b_c{b};
+  VERIFY( Test::ctors() == 1 and Test::copy == 1 );
+  Test::reset();
+
+  optional<Test> b_m{std::move(b)};
+  VERIFY( Test::ctors() == 1 and Test::moved == 1 );
+  Test::reset();
+
+  {
+    optional<Test> b_c2{b};
+    VERIFY( Test::ctors() == 1 and Test::copy == 1 );
+  }
+  VERIFY( Test::dtor == 1 );
+  Test::reset();
+
+  std::make_optional(Test{1});
+  VERIFY( Test::ctors() == 1 and Test::moved == 1 );
+  Test::reset();
+
+  optional<Test> d(std::in_place, 1, 2);
+  VERIFY( Test::ctors() == 1 and Test::ctor2 == 1);
+  Test::reset();
+}
+
+int
+main()
+{
+  test01();
+  return 0;
+}
diff --git a/libstdc++-v3/testsuite/20_util/optional/constructors/ctors.cc b/libstdc++-v3/testsuite/20_util/optional/constructors/ctors.cc
new file mode 100644
index 0000000..e43b84e
--- /dev/null
+++ b/libstdc++-v3/testsuite/20_util/optional/constructors/ctors.cc
@@ -0,0 +1,78 @@
+// { dg-options "-std=gnu++1y" }
+//
+// Copyright (C) 2013 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 copy of the GNU General Public License along
+// with this library; see the file COPYING3.  If not see
+// <http://www.gnu.org/licenses/>.
+
+#include <optional>
+#include <testsuite_hooks.h>
+
+using std::optional;
+using std::nullopt;
+
+void
+test01()
+{
+  // null
+  optional<unsigned> a;
+  VERIFY( not a );
+  VERIFY( a == nullopt );
+
+  optional<unsigned> b(nullopt);
+  VERIFY( not b );
+  VERIFY( b == nullopt );
+
+  // value
+  optional<unsigned> c{0xffu};
+  VERIFY( c );
+  VERIFY( c.value() == 0xffu );
+  VERIFY( *c == 0xffu );
+
+  // copy
+  optional<unsigned> a_c(a);
+  VERIFY( not a_c );
+  VERIFY( a_c == nullopt );
+
+  optional<unsigned> b_c{b};
+  VERIFY( not b_c );
+  VERIFY( b_c == nullopt );
+
+  optional<unsigned> c_c{c};
+  VERIFY( c_c );
+  VERIFY( c_c.value() == 0xffu );
+  VERIFY( *c_c == 0xffu );
+
+  // r-values
+  optional<unsigned> a_m(move(a));
+  VERIFY( not a_m );
+  VERIFY( a_m == nullopt );
+
+  optional<unsigned> b_m{move(b)};
+  VERIFY( not b_m);
+  VERIFY( b_m == nullopt );
+
+  optional<unsigned> c_m{move(c)};
+  VERIFY( c_m );
+  VERIFY( c_m.value() == 0xffu );
+  VERIFY( *c_m == 0xffu );
+}
+
+int
+main()
+{
+  test01();
+  return 0;
+}
diff --git a/libstdc++-v3/testsuite/20_util/optional/hash/hash.cc b/libstdc++-v3/testsuite/20_util/optional/hash/hash.cc
new file mode 100644
index 0000000..b77efa0
--- /dev/null
+++ b/libstdc++-v3/testsuite/20_util/optional/hash/hash.cc
@@ -0,0 +1,57 @@
+// { dg-options "-std=gnu++1y" }
+//
+// Copyright (C) 2013 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 copy of the GNU General Public License along
+// with this library; see the file COPYING3.  If not see
+// <http://www.gnu.org/licenses/>.
+
+#include <optional>
+#include <string>
+#include <testsuite_hooks.h>
+
+using std::string;
+using std::optional;
+
+void
+test01()
+{
+  typedef std::hash<optional<string>> hash_opt;
+  typedef std::hash<string> hash_str;
+
+  optional<string> a;
+  VERIFY(not a);
+  optional<string> b;
+  VERIFY(not b);
+
+  VERIFY(hash_opt{}(a) == hash_opt{}(b));
+
+  a.emplace("hello world");
+  string x{"hello world"};
+  string y{"hallo welt"};
+
+  VERIFY(hash_opt{}(a) == hash_str{}(*a));
+  VERIFY(hash_opt{}(a) == hash_str{}(x));
+  VERIFY(hash_opt{}(a) != hash_str{}(y));
+  VERIFY(hash_opt{}(a) != hash_opt{}(b));
+  b = y;
+  VERIFY(hash_opt{}(a) != hash_opt{}(b));
+}
+
+int
+main()
+{
+  test01();
+  return 0;
+}
diff --git a/libstdc++-v3/testsuite/20_util/optional/observers/observers.cc b/libstdc++-v3/testsuite/20_util/optional/observers/observers.cc
new file mode 100644
index 0000000..dcccdd4
--- /dev/null
+++ b/libstdc++-v3/testsuite/20_util/optional/observers/observers.cc
@@ -0,0 +1,111 @@
+// { dg-options "-std=gnu++1y" }
+//
+// Copyright (C) 2013 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 copy of the GNU General Public License along
+// with this library; see the file COPYING3.  If not see
+// <http://www.gnu.org/licenses/>.
+
+#include <optional>
+#include <testsuite_hooks.h>
+
+using std::optional;
+
+struct Test
+{
+  int a = 0;
+  int b = 0;
+
+  explicit
+  Test(int a = 0, int b = 0)
+    : a(a), b(b)
+  { }
+};
+
+void
+test01()
+{
+  optional<int> a;
+  VERIFY( not a );
+  VERIFY( a.value_or(1) == 1 );
+
+  optional<int> b{1};
+  VERIFY( b );
+  VERIFY( b.value() == 1 );
+  VERIFY( *b == 1 );
+  *b = 2;
+  VERIFY( b );
+  VERIFY( b.value() == 2 );
+  VERIFY( *b == 2 );
+  b.value() = 3;
+  VERIFY( b );
+  VERIFY( b.value() == 3 );
+  VERIFY( *b == 3 );
+  VERIFY( b.value_or(-1) == 3 );
+
+  optional<int> const c{2};
+  VERIFY( c );
+  VERIFY( c.value() == 2 );
+  VERIFY( *c == 2 );
+  VERIFY( c.value_or(-1) == 2 );
+
+  bool throwed = false;
+  optional<Test> d;
+  VERIFY( not d );
+  try
+    {
+      d.value();
+    }
+  catch(std::bad_optional_access&)
+    {
+      throwed = true;
+    }
+  VERIFY( throwed );
+  VERIFY( d.value_or(Test{0xffu}).a == 0xffu );
+
+  optional<Test> e{std::in_place, 1, 2};
+  VERIFY( e );
+  VERIFY( e.value().a == 1 );
+  VERIFY( e.value().b == 2 );
+  VERIFY( (*e).a == 1 );
+  VERIFY( (*e).b == 2 );
+  VERIFY( e->a == 1 );
+  VERIFY( e->b == 2 );
+  e.value().a = 3;
+  VERIFY( e->a == 3 );
+  e->b = 4;
+  VERIFY( (*e).b == 4 );
+  (*e).a = -1;
+  VERIFY( e.value().a == -1 );
+  VERIFY( e.value_or(Test{0xffu}).a == -1 );
+
+  optional<Test> const f(std::in_place, -1);
+  VERIFY( f );
+  VERIFY( f.value().a == -1 );
+  VERIFY( f.value().b ==  0 );
+  VERIFY( (*f).a == -1 );
+  VERIFY( (*f).b ==  0 );
+  VERIFY( f->a == -1 );
+  VERIFY( f->b ==  0 );
+  VERIFY( f.value_or(Test{0xffu}).a == -1 );
+
+  // TODO constexpr!
+}
+
+int
+main()
+{
+  test01();
+  return 0;
+}
diff --git a/libstdc++-v3/testsuite/20_util/optional/swap/swap.cc b/libstdc++-v3/testsuite/20_util/optional/swap/swap.cc
new file mode 100644
index 0000000..77caaea
--- /dev/null
+++ b/libstdc++-v3/testsuite/20_util/optional/swap/swap.cc
@@ -0,0 +1,77 @@
+// { dg-options "-std=gnu++1y" }
+//
+// Copyright (C) 2013 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 copy of the GNU General Public License along
+// with this library; see the file COPYING3.  If not see
+// <http://www.gnu.org/licenses/>.
+
+#include <optional>
+#include <utility>
+#include <testsuite_hooks.h>
+
+using std::optional;
+using std::nullopt;
+using std::swap;
+
+void
+test01()
+{
+  optional<unsigned> a;
+  optional<unsigned> b{nullopt};
+  VERIFY(not a);
+  VERIFY(not b);
+  a.swap(b);
+  VERIFY(not a);
+  VERIFY(not b);
+  swap(a, b);
+  VERIFY(not a);
+  VERIFY(not b);
+
+  optional<unsigned> c{1u};
+  VERIFY(c);
+  VERIFY(c == 1u);
+  a.swap(c);
+  VERIFY(not c);
+  VERIFY(a);
+  VERIFY(a == 1u);
+  swap(b, c);
+  VERIFY(not b);
+  VERIFY(not c);
+  swap(c, a);
+  VERIFY(c);
+  VERIFY(c == 1u);
+  VERIFY(not a);
+
+  optional<unsigned> d{0xffu};
+  VERIFY(d);
+  VERIFY(d == 0xffu);
+  d.swap(c);
+  VERIFY(d);
+  VERIFY(d == 1u);
+  VERIFY(c);
+  VERIFY(c == 0xffu);
+  swap(d, c);
+  VERIFY(d);
+  VERIFY(d == 0xffu);
+  VERIFY(c);
+  VERIFY(c == 1u);
+}
+
+int
+main()
+{
+  test01();
+  return 0;
+}
-- 
1.8.4


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]