This is the mail archive of the
libstdc++@gcc.gnu.org
mailing list for the libstdc++ project.
[RFC-2] Add C++14's optional type (20.6/n3672).
- From: Rüdiger Sonderfeld <ruediger at c-plusplus dot de>
- To: libstdc++ at gcc dot gnu dot org
- Date: Wed, 25 Sep 2013 18:24:02 +0200
- Subject: [RFC-2] Add C++14's optional type (20.6/n3672).
- Authentication-results: sourceware.org; auth=none
- References: <1911669 dot rpbxtoy5JO at descartes>
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