From 435e56fb5289d72bfe12068aac72e76c02bb3b3c Mon Sep 17 00:00:00 2001 From: Ville Voutilainen Date: Sun, 10 Jul 2016 20:44:21 +0300 Subject: [PATCH] Implement std::optional. * include/Makefile.am: Add optional to exported headers. * include/Makefile.in: Likewise. * include/std/optional: New. * testsuite/20_util/optional/typedefs.cc: Likewise. * testsuite/20_util/optional/relops/2.cc: Likewise. * testsuite/20_util/optional/relops/3.cc: Likewise. * testsuite/20_util/optional/relops/4.cc: Likewise. * testsuite/20_util/optional/relops/5.cc: Likewise. * testsuite/20_util/optional/relops/1.cc: Likewise. * testsuite/20_util/optional/relops/6.cc: Likewise. * testsuite/20_util/optional/nullopt.cc: Likewise. * testsuite/20_util/optional/in_place.cc: Likewise. * testsuite/20_util/optional/make_optional.cc: Likewise. * testsuite/20_util/optional/assignment/2.cc: Likewise. * testsuite/20_util/optional/assignment/3.cc: Likewise. * testsuite/20_util/optional/assignment/4.cc: Likewise. * testsuite/20_util/optional/assignment/5.cc: Likewise. * testsuite/20_util/optional/assignment/1.cc: Likewise. * testsuite/20_util/optional/assignment/6.cc: Likewise. * testsuite/20_util/optional/cons/value_neg.cc: Likewise. * testsuite/20_util/optional/cons/default.cc: Likewise. * testsuite/20_util/optional/cons/move.cc: Likewise. * testsuite/20_util/optional/cons/value.cc: Likewise. * testsuite/20_util/optional/cons/copy.cc: Likewise. * testsuite/20_util/optional/requirements.cc: Likewise. * testsuite/20_util/optional/observers/2.cc: Likewise. * testsuite/20_util/optional/observers/3.cc: Likewise. * testsuite/20_util/optional/observers/4.cc: Likewise. * testsuite/20_util/optional/observers/5.cc: Likewise. * testsuite/20_util/optional/observers/1.cc: Likewise. * testsuite/20_util/optional/constexpr/relops/2.cc: Likewise. * testsuite/20_util/optional/constexpr/relops/3.cc: Likewise. * testsuite/20_util/optional/constexpr/relops/4.cc: Likewise. * testsuite/20_util/optional/constexpr/relops/5.cc: Likewise. * testsuite/20_util/optional/constexpr/relops/1.cc: Likewise. * testsuite/20_util/optional/constexpr/relops/6.cc: Likewise. * testsuite/20_util/optional/constexpr/nullopt.cc: Likewise. * testsuite/20_util/optional/constexpr/in_place.cc: Likewise. * testsuite/20_util/optional/constexpr/make_optional.cc: Likewise. * testsuite/20_util/optional/constexpr/cons/default.cc: Likewise. * testsuite/20_util/optional/constexpr/cons/value.cc: Likewise. * testsuite/20_util/optional/constexpr/observers/2.cc: Likewise. * testsuite/20_util/optional/constexpr/observers/3.cc: Likewise. * testsuite/20_util/optional/constexpr/observers/4.cc: Likewise. * testsuite/20_util/optional/constexpr/observers/5.cc: Likewise. * testsuite/20_util/optional/constexpr/observers/1.cc: Likewise. * testsuite/20_util/optional/swap/1.cc: Likewise. From-SVN: r238197 --- libstdc++-v3/ChangeLog | 51 + libstdc++-v3/include/Makefile.am | 1 + libstdc++-v3/include/Makefile.in | 1 + libstdc++-v3/include/std/optional | 983 ++++++++++++++++++ .../20_util/optional/assignment/1.cc | 195 ++++ .../20_util/optional/assignment/2.cc | 193 ++++ .../20_util/optional/assignment/3.cc | 158 +++ .../20_util/optional/assignment/4.cc | 158 +++ .../20_util/optional/assignment/5.cc | 66 ++ .../20_util/optional/assignment/6.cc | 83 ++ .../testsuite/20_util/optional/cons/copy.cc | 126 +++ .../20_util/optional/cons/default.cc | 60 ++ .../testsuite/20_util/optional/cons/move.cc | 126 +++ .../testsuite/20_util/optional/cons/value.cc | 258 +++++ .../20_util/optional/cons/value_neg.cc | 39 + .../optional/constexpr/cons/default.cc | 42 + .../20_util/optional/constexpr/cons/value.cc | 69 ++ .../20_util/optional/constexpr/in_place.cc | 43 + .../optional/constexpr/make_optional.cc | 30 + .../20_util/optional/constexpr/nullopt.cc | 46 + .../20_util/optional/constexpr/observers/1.cc | 32 + .../20_util/optional/constexpr/observers/2.cc | 35 + .../20_util/optional/constexpr/observers/3.cc | 33 + .../20_util/optional/constexpr/observers/4.cc | 34 + .../20_util/optional/constexpr/observers/5.cc | 39 + .../20_util/optional/constexpr/relops/1.cc | 99 ++ .../20_util/optional/constexpr/relops/2.cc | 111 ++ .../20_util/optional/constexpr/relops/3.cc | 89 ++ .../20_util/optional/constexpr/relops/4.cc | 101 ++ .../20_util/optional/constexpr/relops/5.cc | 80 ++ .../20_util/optional/constexpr/relops/6.cc | 88 ++ .../testsuite/20_util/optional/in_place.cc | 66 ++ .../20_util/optional/make_optional.cc | 31 + .../testsuite/20_util/optional/nullopt.cc | 46 + .../testsuite/20_util/optional/observers/1.cc | 33 + .../testsuite/20_util/optional/observers/2.cc | 37 + .../testsuite/20_util/optional/observers/3.cc | 58 ++ .../testsuite/20_util/optional/observers/4.cc | 35 + .../testsuite/20_util/optional/observers/5.cc | 40 + .../testsuite/20_util/optional/relops/1.cc | 85 ++ .../testsuite/20_util/optional/relops/2.cc | 97 ++ .../testsuite/20_util/optional/relops/3.cc | 75 ++ .../testsuite/20_util/optional/relops/4.cc | 87 ++ .../testsuite/20_util/optional/relops/5.cc | 66 ++ .../testsuite/20_util/optional/relops/6.cc | 74 ++ .../20_util/optional/requirements.cc | 259 +++++ .../testsuite/20_util/optional/swap/1.cc | 95 ++ .../testsuite/20_util/optional/typedefs.cc | 33 + 48 files changed, 4686 insertions(+) create mode 100644 libstdc++-v3/include/std/optional create mode 100644 libstdc++-v3/testsuite/20_util/optional/assignment/1.cc create mode 100644 libstdc++-v3/testsuite/20_util/optional/assignment/2.cc create mode 100644 libstdc++-v3/testsuite/20_util/optional/assignment/3.cc create mode 100644 libstdc++-v3/testsuite/20_util/optional/assignment/4.cc create mode 100644 libstdc++-v3/testsuite/20_util/optional/assignment/5.cc create mode 100644 libstdc++-v3/testsuite/20_util/optional/assignment/6.cc create mode 100644 libstdc++-v3/testsuite/20_util/optional/cons/copy.cc create mode 100644 libstdc++-v3/testsuite/20_util/optional/cons/default.cc create mode 100644 libstdc++-v3/testsuite/20_util/optional/cons/move.cc create mode 100644 libstdc++-v3/testsuite/20_util/optional/cons/value.cc create mode 100644 libstdc++-v3/testsuite/20_util/optional/cons/value_neg.cc create mode 100644 libstdc++-v3/testsuite/20_util/optional/constexpr/cons/default.cc create mode 100644 libstdc++-v3/testsuite/20_util/optional/constexpr/cons/value.cc create mode 100644 libstdc++-v3/testsuite/20_util/optional/constexpr/in_place.cc create mode 100644 libstdc++-v3/testsuite/20_util/optional/constexpr/make_optional.cc create mode 100644 libstdc++-v3/testsuite/20_util/optional/constexpr/nullopt.cc create mode 100644 libstdc++-v3/testsuite/20_util/optional/constexpr/observers/1.cc create mode 100644 libstdc++-v3/testsuite/20_util/optional/constexpr/observers/2.cc create mode 100644 libstdc++-v3/testsuite/20_util/optional/constexpr/observers/3.cc create mode 100644 libstdc++-v3/testsuite/20_util/optional/constexpr/observers/4.cc create mode 100644 libstdc++-v3/testsuite/20_util/optional/constexpr/observers/5.cc create mode 100644 libstdc++-v3/testsuite/20_util/optional/constexpr/relops/1.cc create mode 100644 libstdc++-v3/testsuite/20_util/optional/constexpr/relops/2.cc create mode 100644 libstdc++-v3/testsuite/20_util/optional/constexpr/relops/3.cc create mode 100644 libstdc++-v3/testsuite/20_util/optional/constexpr/relops/4.cc create mode 100644 libstdc++-v3/testsuite/20_util/optional/constexpr/relops/5.cc create mode 100644 libstdc++-v3/testsuite/20_util/optional/constexpr/relops/6.cc create mode 100644 libstdc++-v3/testsuite/20_util/optional/in_place.cc create mode 100644 libstdc++-v3/testsuite/20_util/optional/make_optional.cc create mode 100644 libstdc++-v3/testsuite/20_util/optional/nullopt.cc create mode 100644 libstdc++-v3/testsuite/20_util/optional/observers/1.cc create mode 100644 libstdc++-v3/testsuite/20_util/optional/observers/2.cc create mode 100644 libstdc++-v3/testsuite/20_util/optional/observers/3.cc create mode 100644 libstdc++-v3/testsuite/20_util/optional/observers/4.cc create mode 100644 libstdc++-v3/testsuite/20_util/optional/observers/5.cc create mode 100644 libstdc++-v3/testsuite/20_util/optional/relops/1.cc create mode 100644 libstdc++-v3/testsuite/20_util/optional/relops/2.cc create mode 100644 libstdc++-v3/testsuite/20_util/optional/relops/3.cc create mode 100644 libstdc++-v3/testsuite/20_util/optional/relops/4.cc create mode 100644 libstdc++-v3/testsuite/20_util/optional/relops/5.cc create mode 100644 libstdc++-v3/testsuite/20_util/optional/relops/6.cc create mode 100644 libstdc++-v3/testsuite/20_util/optional/requirements.cc create mode 100644 libstdc++-v3/testsuite/20_util/optional/swap/1.cc create mode 100644 libstdc++-v3/testsuite/20_util/optional/typedefs.cc diff --git a/libstdc++-v3/ChangeLog b/libstdc++-v3/ChangeLog index f1529c2f1a8..0aee6800828 100644 --- a/libstdc++-v3/ChangeLog +++ b/libstdc++-v3/ChangeLog @@ -1,3 +1,54 @@ +2016-07-10 Ville Voutilainen + + Implement std::optional. + * include/Makefile.am: Add optional to exported headers. + * include/Makefile.in: Likewise. + * include/std/optional: New. + * testsuite/20_util/optional/typedefs.cc: Likewise. + * testsuite/20_util/optional/relops/2.cc: Likewise. + * testsuite/20_util/optional/relops/3.cc: Likewise. + * testsuite/20_util/optional/relops/4.cc: Likewise. + * testsuite/20_util/optional/relops/5.cc: Likewise. + * testsuite/20_util/optional/relops/1.cc: Likewise. + * testsuite/20_util/optional/relops/6.cc: Likewise. + * testsuite/20_util/optional/nullopt.cc: Likewise. + * testsuite/20_util/optional/in_place.cc: Likewise. + * testsuite/20_util/optional/make_optional.cc: Likewise. + * testsuite/20_util/optional/assignment/2.cc: Likewise. + * testsuite/20_util/optional/assignment/3.cc: Likewise. + * testsuite/20_util/optional/assignment/4.cc: Likewise. + * testsuite/20_util/optional/assignment/5.cc: Likewise. + * testsuite/20_util/optional/assignment/1.cc: Likewise. + * testsuite/20_util/optional/assignment/6.cc: Likewise. + * testsuite/20_util/optional/cons/value_neg.cc: Likewise. + * testsuite/20_util/optional/cons/default.cc: Likewise. + * testsuite/20_util/optional/cons/move.cc: Likewise. + * testsuite/20_util/optional/cons/value.cc: Likewise. + * testsuite/20_util/optional/cons/copy.cc: Likewise. + * testsuite/20_util/optional/requirements.cc: Likewise. + * testsuite/20_util/optional/observers/2.cc: Likewise. + * testsuite/20_util/optional/observers/3.cc: Likewise. + * testsuite/20_util/optional/observers/4.cc: Likewise. + * testsuite/20_util/optional/observers/5.cc: Likewise. + * testsuite/20_util/optional/observers/1.cc: Likewise. + * testsuite/20_util/optional/constexpr/relops/2.cc: Likewise. + * testsuite/20_util/optional/constexpr/relops/3.cc: Likewise. + * testsuite/20_util/optional/constexpr/relops/4.cc: Likewise. + * testsuite/20_util/optional/constexpr/relops/5.cc: Likewise. + * testsuite/20_util/optional/constexpr/relops/1.cc: Likewise. + * testsuite/20_util/optional/constexpr/relops/6.cc: Likewise. + * testsuite/20_util/optional/constexpr/nullopt.cc: Likewise. + * testsuite/20_util/optional/constexpr/in_place.cc: Likewise. + * testsuite/20_util/optional/constexpr/make_optional.cc: Likewise. + * testsuite/20_util/optional/constexpr/cons/default.cc: Likewise. + * testsuite/20_util/optional/constexpr/cons/value.cc: Likewise. + * testsuite/20_util/optional/constexpr/observers/2.cc: Likewise. + * testsuite/20_util/optional/constexpr/observers/3.cc: Likewise. + * testsuite/20_util/optional/constexpr/observers/4.cc: Likewise. + * testsuite/20_util/optional/constexpr/observers/5.cc: Likewise. + * testsuite/20_util/optional/constexpr/observers/1.cc: Likewise. + * testsuite/20_util/optional/swap/1.cc: Likewise. + 2016-07-08 Jonathan Wakely * testsuite/23_containers/vector/modifiers/insert/aliasing.cc: New. diff --git a/libstdc++-v3/include/Makefile.am b/libstdc++-v3/include/Makefile.am index 4c9cb06e095..4bc33543a47 100644 --- a/libstdc++-v3/include/Makefile.am +++ b/libstdc++-v3/include/Makefile.am @@ -53,6 +53,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/Makefile.in b/libstdc++-v3/include/Makefile.in index bddeb885c10..1f255a9bbc6 100644 --- a/libstdc++-v3/include/Makefile.in +++ b/libstdc++-v3/include/Makefile.in @@ -343,6 +343,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/std/optional b/libstdc++-v3/include/std/optional new file mode 100644 index 00000000000..e9a86a44aa2 --- /dev/null +++ b/libstdc++-v3/include/std/optional @@ -0,0 +1,983 @@ +// -*- C++ -*- + +// Copyright (C) 2013-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. + +// 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 +// . + +/** @file include/optional + * This is a Standard C++ Library header. + */ + +#ifndef _GLIBCXX_OPTIONAL +#define _GLIBCXX_OPTIONAL 1 + +#if __cplusplus <= 201402L +# include +#else + +#include +#include +#include +#include +#include +#include +#include +#include + +namespace std _GLIBCXX_VISIBILITY(default) +{ +_GLIBCXX_BEGIN_NAMESPACE_VERSION + + /** + * @addtogroup utilities + * @{ + */ + + // All subsequent [X.Y.n] references are against n3793. + + // [X.Y.4] + template + 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 + { + // Do not user-declare default constructor at all for + // optional_value = {} syntax to work. + // nullopt_t() = delete; + + // Used for constructing nullopt. + enum class _Construct { _Token }; + + // Must be constexpr for nullopt_t to be literal. + explicit constexpr nullopt_t(_Construct) { } + }; + + // [X.Y.6] + /// Tag to disengage optional objects. + constexpr nullopt_t nullopt { nullopt_t::_Construct::_Token }; + + // [X.Y.7] + /** + * @brief Exception class thrown when a disengaged optional object is + * dereferenced. + * @ingroup exceptions + */ + class bad_optional_access : public logic_error + { + 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) { } + + virtual ~bad_optional_access() noexcept = default; + }; + + void + __throw_bad_optional_access(const char*) + __attribute__((__noreturn__)); + + // XXX Does not belong here. + inline void + __throw_bad_optional_access(const char* __s) + { _GLIBCXX_THROW_OR_ABORT(bad_optional_access(__s)); } + + template + struct _Has_addressof_mem : std::false_type { }; + + template + struct _Has_addressof_mem<_Tp, + __void_t().operator&() )> + > + : std::true_type { }; + + template + struct _Has_addressof_free : std::false_type { }; + + template + struct _Has_addressof_free<_Tp, + __void_t()) )> + > + : std::true_type { }; + + /** + * @brief Trait that detects the presence of an overloaded unary operator&. + * + * Practically speaking this detects the presence of such an operator when + * called on a const-qualified lvalue (i.e. + * declval<_Tp * const&>().operator&()). + */ + template + struct _Has_addressof + : std::__or_<_Has_addressof_mem<_Tp>, _Has_addressof_free<_Tp>>::type + { }; + + /** + * @brief An overload that attempts to take the address of an lvalue as a + * constant expression. Falls back to __addressof in the presence of an + * overloaded addressof operator (unary operator&), in which case the call + * will not be a constant expression. + */ + template::value, int>...> + constexpr _Tp* __constexpr_addressof(_Tp& __t) + { return &__t; } + + /** + * @brief Fallback overload that defers to __addressof. + */ + template::value, int>...> + inline _Tp* __constexpr_addressof(_Tp& __t) + { return std::__addressof(__t); } + + /** + * @brief Class template that holds the necessary state for @ref optional + * and that has the responsibility for construction and the special members. + * + * Such a separate base class template is necessary in order to + * conditionally enable the special members (e.g. copy/move constructors). + * Note that this means that @ref _Optional_base implements the + * functionality for copy and move assignment, but not for converting + * assignment. + * + * @see optional, _Enable_special_members + */ + template::value> + class _Optional_base + { + private: + // Remove const to avoid prohibition of reusing object storage for + // const-qualified types in [3.8/9]. This is strictly internal + // and even optional itself is oblivious to it. + using _Stored_type = remove_const_t<_Tp>; + + public: + // [X.Y.4.1] Constructors. + + // Constructors for disengaged optionals. + constexpr _Optional_base() noexcept + : _M_empty{} { } + + constexpr _Optional_base(nullopt_t) noexcept + : _Optional_base{} { } + + // Constructors for engaged optionals. + constexpr _Optional_base(const _Tp& __t) + : _M_payload(__t), _M_engaged(true) { } + + constexpr _Optional_base(_Tp&& __t) + : _M_payload(std::move(__t)), _M_engaged(true) { } + + template + constexpr explicit _Optional_base(in_place_t, _Args&&... __args) + : _M_payload(std::forward<_Args>(__args)...), _M_engaged(true) { } + + template&, + _Args&&...>::value, + int>...> + constexpr explicit _Optional_base(in_place_t, + initializer_list<_Up> __il, + _Args&&... __args) + : _M_payload(__il, std::forward<_Args>(__args)...), + _M_engaged(true) { } + + // Copy and move constructors. + _Optional_base(const _Optional_base& __other) + { + if (__other._M_engaged) + this->_M_construct(__other._M_get()); + } + + _Optional_base(_Optional_base&& __other) + noexcept(is_nothrow_move_constructible<_Tp>()) + { + if (__other._M_engaged) + this->_M_construct(std::move(__other._M_get())); + } + + // [X.Y.4.3] (partly) Assignment. + _Optional_base& + operator=(const _Optional_base& __other) + { + if (this->_M_engaged && __other._M_engaged) + this->_M_get() = __other._M_get(); + else + { + if (__other._M_engaged) + this->_M_construct(__other._M_get()); + else + this->_M_reset(); + } + + return *this; + } + + _Optional_base& + operator=(_Optional_base&& __other) + noexcept(__and_, + is_nothrow_move_assignable<_Tp>>()) + { + if (this->_M_engaged && __other._M_engaged) + this->_M_get() = std::move(__other._M_get()); + else + { + if (__other._M_engaged) + this->_M_construct(std::move(__other._M_get())); + else + this->_M_reset(); + } + return *this; + } + + // [X.Y.4.2] Destructor. + ~_Optional_base() + { + if (this->_M_engaged) + this->_M_payload.~_Stored_type(); + } + + // The following functionality is also needed by optional, hence the + // protected accessibility. + protected: + constexpr bool _M_is_engaged() const noexcept + { return this->_M_engaged; } + + // The _M_get operations have _M_engaged as a precondition. + constexpr _Tp& + _M_get() noexcept + { return _M_payload; } + + constexpr const _Tp& + _M_get() const noexcept + { return _M_payload; } + + // The _M_construct operation has !_M_engaged as a precondition + // while _M_destruct has _M_engaged as a precondition. + template + void + _M_construct(_Args&&... __args) + noexcept(is_nothrow_constructible<_Stored_type, _Args...>()) + { + ::new (std::__addressof(this->_M_payload)) + _Stored_type(std::forward<_Args>(__args)...); + this->_M_engaged = true; + } + + void + _M_destruct() + { + this->_M_engaged = false; + this->_M_payload.~_Stored_type(); + } + + // _M_reset is a 'safe' operation with no precondition. + void + _M_reset() + { + if (this->_M_engaged) + this->_M_destruct(); + } + + private: + struct _Empty_byte { }; + union { + _Empty_byte _M_empty; + _Stored_type _M_payload; + }; + bool _M_engaged = false; + }; + + /// Partial specialization that is exactly identical to the primary template + /// save for not providing a destructor, to fulfill triviality requirements. + template + class _Optional_base<_Tp, false> + { + private: + using _Stored_type = remove_const_t<_Tp>; + + public: + constexpr _Optional_base() noexcept + : _M_empty{} { } + + constexpr _Optional_base(nullopt_t) noexcept + : _Optional_base{} { } + + constexpr _Optional_base(const _Tp& __t) + : _M_payload(__t), _M_engaged(true) { } + + constexpr _Optional_base(_Tp&& __t) + : _M_payload(std::move(__t)), _M_engaged(true) { } + + template + constexpr explicit _Optional_base(in_place_t, _Args&&... __args) + : _M_payload(std::forward<_Args>(__args)...), _M_engaged(true) { } + + template&, + _Args&&...>::value, + int>...> + constexpr explicit _Optional_base(in_place_t, + initializer_list<_Up> __il, + _Args&&... __args) + : _M_payload(__il, std::forward<_Args>(__args)...), + _M_engaged(true) { } + + _Optional_base(const _Optional_base& __other) + { + if (__other._M_engaged) + this->_M_construct(__other._M_get()); + } + + _Optional_base(_Optional_base&& __other) + noexcept(is_nothrow_move_constructible<_Tp>()) + { + if (__other._M_engaged) + this->_M_construct(std::move(__other._M_get())); + } + + _Optional_base& + operator=(const _Optional_base& __other) + { + if (this->_M_engaged && __other._M_engaged) + this->_M_get() = __other._M_get(); + else + { + if (__other._M_engaged) + this->_M_construct(__other._M_get()); + else + this->_M_reset(); + } + return *this; + } + + _Optional_base& + operator=(_Optional_base&& __other) + noexcept(__and_, + is_nothrow_move_assignable<_Tp>>()) + { + if (this->_M_engaged && __other._M_engaged) + this->_M_get() = std::move(__other._M_get()); + else + { + if (__other._M_engaged) + this->_M_construct(std::move(__other._M_get())); + else + this->_M_reset(); + } + return *this; + } + + // Sole difference + // ~_Optional_base() noexcept = default; + + protected: + constexpr bool _M_is_engaged() const noexcept + { return this->_M_engaged; } + + _Tp& + _M_get() noexcept + { return _M_payload; } + + constexpr const _Tp& + _M_get() const noexcept + { return _M_payload; } + + template + void + _M_construct(_Args&&... __args) + noexcept(is_nothrow_constructible<_Stored_type, _Args...>()) + { + ::new (std::__addressof(this->_M_payload)) + _Stored_type(std::forward<_Args>(__args)...); + this->_M_engaged = true; + } + + void + _M_destruct() + { + this->_M_engaged = false; + this->_M_payload.~_Stored_type(); + } + + void + _M_reset() + { + if (this->_M_engaged) + this->_M_destruct(); + } + + private: + struct _Empty_byte { }; + union + { + _Empty_byte _M_empty; + _Stored_type _M_payload; + }; + bool _M_engaged = false; + }; + + template + class optional; + + template + struct __is_optional_impl : false_type + { }; + + template + struct __is_optional_impl> : true_type + { }; + + template + struct __is_optional + : public __is_optional_impl>> + { }; + + + /** + * @brief Class template for optional values. + */ + template + class optional + : private _Optional_base<_Tp>, + private _Enable_copy_move< + // Copy constructor. + is_copy_constructible<_Tp>::value, + // Copy assignment. + __and_, is_copy_assignable<_Tp>>::value, + // Move constructor. + is_move_constructible<_Tp>::value, + // Move assignment. + __and_, is_move_assignable<_Tp>>::value, + // Unique tag type. + optional<_Tp>> + { + static_assert(__and_<__not_, nullopt_t>>, + __not_, in_place_t>>, + __not_>>(), + "Invalid instantiation of optional"); + + private: + using _Base = _Optional_base<_Tp>; + + public: + using value_type = _Tp; + + // _Optional_base has the responsibility for construction. + using _Base::_Base; + + constexpr optional() = default; + // Converting constructors for engaged optionals. + template >, + is_constructible<_Tp, _Up&&>, + is_convertible<_Up&&, _Tp> + >::value, bool> = true> + constexpr optional(_Up&& __t) + : _Base(_Tp(std::forward<_Up>(__t))) { } + + template >, + is_constructible<_Tp, _Up&&>, + __not_> + >::value, bool> = false> + explicit constexpr optional(_Up&& __t) + : _Base(_Tp(std::forward<_Up>(__t))) { } + + template >, + __not_&>>, + __not_&, _Tp>>, + is_constructible<_Tp, const _Up&>, + is_convertible + >::value, bool> = true> + constexpr optional(const optional<_Up>& __t) + : _Base(__t ? optional<_Tp>(*__t) : optional<_Tp>()) { } + + template >, + __not_&>>, + __not_&, _Tp>>, + is_constructible<_Tp, const _Up&>, + __not_> + >::value, bool> = false> + explicit constexpr optional(const optional<_Up>& __t) + : _Base(__t ? optional<_Tp>(*__t) : optional<_Tp>()) { } + + template >, + __not_&&>>, + __not_&&, _Tp>>, + is_constructible<_Tp, _Up&&>, + is_convertible<_Up&&, _Tp> + >::value, bool> = true> + constexpr optional(optional<_Up>&& __t) + : _Base(__t ? optional<_Tp>(std::move(*__t)) : optional<_Tp>()) { } + + template >, + __not_&&>>, + __not_&&, _Tp>>, + is_constructible<_Tp, _Up&&>, + __not_> + >::value, bool> = false> + explicit constexpr optional(optional<_Up>&& __t) + : _Base(__t ? optional<_Tp>(std::move(*__t)) : optional<_Tp>()) { } + + // [X.Y.4.3] (partly) Assignment. + optional& + operator=(nullopt_t) noexcept + { + this->_M_reset(); + return *this; + } + + template>, + __not_<__is_optional<_Up>>>::value, + bool> = true> + optional& + operator=(_Up&& __u) + { + static_assert(__and_, + is_assignable<_Tp&, _Up>>(), + "Cannot assign to value type from argument"); + + if (this->_M_is_engaged()) + this->_M_get() = std::forward<_Up>(__u); + else + this->_M_construct(std::forward<_Up>(__u)); + + return *this; + } + + template>>::value, + bool> = true> + optional& + operator=(const optional<_Up>& __u) + { + static_assert(__and_, + is_assignable<_Tp&, _Up>>(), + "Cannot assign to value type from argument"); + + if (__u) + { + if (this->_M_is_engaged()) + this->_M_get() = *__u; + else + this->_M_construct(*__u); + } + else + { + this->_M_reset(); + } + return *this; + } + + template>>::value, + bool> = true> + optional& + operator=(optional<_Up>&& __u) + { + static_assert(__and_, + is_assignable<_Tp&, _Up>>(), + "Cannot assign to value type from argument"); + + if (__u) + { + if (this->_M_is_engaged()) + this->_M_get() = std::move(*__u); + else + this->_M_construct(std::move(*__u)); + } + else + { + this->_M_reset(); + } + + return *this; + } + + template + void + 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 + enable_if_t&, + _Args&&...>::value> + emplace(initializer_list<_Up> __il, _Args&&... __args) + { + this->_M_reset(); + this->_M_construct(__il, std::forward<_Args>(__args)...); + } + + // [X.Y.4.2] Destructor is implicit, implemented in _Optional_base. + + // [X.Y.4.4] Swap. + void + swap(optional& __other) + noexcept(is_nothrow_move_constructible<_Tp>() + && noexcept(swap(declval<_Tp&>(), declval<_Tp&>()))) + { + using std::swap; + + if (this->_M_is_engaged() && __other._M_is_engaged()) + swap(this->_M_get(), __other._M_get()); + else if (this->_M_is_engaged()) + { + __other._M_construct(std::move(this->_M_get())); + this->_M_destruct(); + } + else if (__other._M_is_engaged()) + { + this->_M_construct(std::move(__other._M_get())); + __other._M_destruct(); + } + } + + // [X.Y.4.5] Observers. + constexpr const _Tp* + operator->() const + { return __constexpr_addressof(this->_M_get()); } + + _Tp* + operator->() + { return std::__addressof(this->_M_get()); } + + constexpr const _Tp& + operator*() const& + { return this->_M_get(); } + + constexpr _Tp& + operator*()& + { return this->_M_get(); } + + constexpr _Tp&& + operator*()&& + { return std::move(this->_M_get()); } + + constexpr const _Tp&& + operator*() const&& + { return std::move(this->_M_get()); } + + constexpr explicit operator bool() const noexcept + { return this->_M_is_engaged(); } + + constexpr const _Tp& + value() const& + { + return this->_M_is_engaged() + ? this->_M_get() + : (__throw_bad_optional_access("Attempt to access value of a " + "disengaged optional object"), + this->_M_get()); + } + + constexpr _Tp& + value()& + { + return this->_M_is_engaged() + ? this->_M_get() + : (__throw_bad_optional_access("Attempt to access value of a " + "disengaged optional object"), + this->_M_get()); + } + + constexpr _Tp&& + value()&& + { + return this->_M_is_engaged() + ? std::move(this->_M_get()) + : (__throw_bad_optional_access("Attempt to access value of a " + "disengaged optional object"), + std::move(this->_M_get())); + } + + constexpr const _Tp&& + value() const&& + { + return this->_M_is_engaged() + ? std::move(this->_M_get()) + : (__throw_bad_optional_access("Attempt to access value of a " + "disengaged optional object"), + std::move(this->_M_get())); + } + + template + constexpr _Tp + value_or(_Up&& __u) const& + { + static_assert(__and_, + is_convertible<_Up&&, _Tp>>(), + "Cannot return value"); + + return this->_M_is_engaged() + ? this->_M_get() + : static_cast<_Tp>(std::forward<_Up>(__u)); + } + + template + _Tp + value_or(_Up&& __u) && + { + static_assert(__and_, + is_convertible<_Up&&, _Tp>>(), + "Cannot return value" ); + + return this->_M_is_engaged() + ? std::move(this->_M_get()) + : static_cast<_Tp>(std::forward<_Up>(__u)); + } + }; + + // [X.Y.8] Comparisons between optional values. + template + constexpr bool + operator==(const optional<_Tp>& __lhs, const optional<_Tp>& __rhs) + { + return static_cast(__lhs) == static_cast(__rhs) + && (!__lhs || *__lhs == *__rhs); + } + + template + constexpr bool + operator!=(const optional<_Tp>& __lhs, const optional<_Tp>& __rhs) + { return !(__lhs == __rhs); } + + template + constexpr bool + operator<(const optional<_Tp>& __lhs, const optional<_Tp>& __rhs) + { + return static_cast(__rhs) && (!__lhs || *__lhs < *__rhs); + } + + template + constexpr bool + operator>(const optional<_Tp>& __lhs, const optional<_Tp>& __rhs) + { return __rhs < __lhs; } + + template + constexpr bool + operator<=(const optional<_Tp>& __lhs, const optional<_Tp>& __rhs) + { return !(__rhs < __lhs); } + + template + constexpr bool + operator>=(const optional<_Tp>& __lhs, const optional<_Tp>& __rhs) + { return !(__lhs < __rhs); } + + // [X.Y.9] Comparisons with nullopt. + template + constexpr bool + operator==(const optional<_Tp>& __lhs, nullopt_t) noexcept + { return !__lhs; } + + template + constexpr bool + operator==(nullopt_t, const optional<_Tp>& __rhs) noexcept + { return !__rhs; } + + template + constexpr bool + operator!=(const optional<_Tp>& __lhs, nullopt_t) noexcept + { return static_cast(__lhs); } + + template + constexpr bool + operator!=(nullopt_t, const optional<_Tp>& __rhs) noexcept + { return static_cast(__rhs); } + + template + constexpr bool + operator<(const optional<_Tp>& /* __lhs */, nullopt_t) noexcept + { return false; } + + template + constexpr bool + operator<(nullopt_t, const optional<_Tp>& __rhs) noexcept + { return static_cast(__rhs); } + + template + constexpr bool + operator>(const optional<_Tp>& __lhs, nullopt_t) noexcept + { return static_cast(__lhs); } + + template + constexpr bool + operator>(nullopt_t, const optional<_Tp>& /* __rhs */) noexcept + { return false; } + + template + constexpr bool + operator<=(const optional<_Tp>& __lhs, nullopt_t) noexcept + { return !__lhs; } + + template + constexpr bool + operator<=(nullopt_t, const optional<_Tp>& /* __rhs */) noexcept + { return true; } + + template + constexpr bool + operator>=(const optional<_Tp>& /* __lhs */, nullopt_t) noexcept + { return true; } + + template + constexpr bool + operator>=(nullopt_t, const optional<_Tp>& __rhs) noexcept + { return !__rhs; } + + // [X.Y.10] Comparisons with value type. + template + constexpr bool + operator==(const optional<_Tp>& __lhs, const _Tp& __rhs) + { return __lhs && *__lhs == __rhs; } + + template + constexpr bool + operator==(const _Tp& __lhs, const optional<_Tp>& __rhs) + { return __rhs && __lhs == *__rhs; } + + template + constexpr bool + operator!=(const optional<_Tp>& __lhs, _Tp const& __rhs) + { return !__lhs || !(*__lhs == __rhs); } + + template + constexpr bool + operator!=(const _Tp& __lhs, const optional<_Tp>& __rhs) + { return !__rhs || !(__lhs == *__rhs); } + + template + constexpr bool + operator<(const optional<_Tp>& __lhs, const _Tp& __rhs) + { return !__lhs || *__lhs < __rhs; } + + template + constexpr bool + operator<(const _Tp& __lhs, const optional<_Tp>& __rhs) + { return __rhs && __lhs < *__rhs; } + + template + constexpr bool + operator>(const optional<_Tp>& __lhs, const _Tp& __rhs) + { return __lhs && __rhs < *__lhs; } + + template + constexpr bool + operator>(const _Tp& __lhs, const optional<_Tp>& __rhs) + { return !__rhs || *__rhs < __lhs; } + + template + constexpr bool + operator<=(const optional<_Tp>& __lhs, const _Tp& __rhs) + { return !__lhs || !(__rhs < *__lhs); } + + template + constexpr bool + operator<=(const _Tp& __lhs, const optional<_Tp>& __rhs) + { return __rhs && !(*__rhs < __lhs); } + + template + constexpr bool + operator>=(const optional<_Tp>& __lhs, const _Tp& __rhs) + { return __lhs && !(*__lhs < __rhs); } + + template + constexpr bool + operator>=(const _Tp& __lhs, const optional<_Tp>& __rhs) + { return !__rhs || !(__lhs < *__rhs); } + + // [X.Y.11] + template + inline void + swap(optional<_Tp>& __lhs, optional<_Tp>& __rhs) + noexcept(noexcept(__lhs.swap(__rhs))) + { __lhs.swap(__rhs); } + + template + constexpr optional> + make_optional(_Tp&& __t) + { return optional> { std::forward<_Tp>(__t) }; } + + // [X.Y.12] + template + struct hash> + { + using result_type = size_t; + using argument_type = optional<_Tp>; + + size_t + operator()(const optional<_Tp>& __t) const + noexcept(noexcept(hash<_Tp> {}(*__t))) + { + // We pick an arbitrary hash for disengaged optionals which hopefully + // usual values of _Tp won't typically hash to. + constexpr size_t __magic_disengaged_hash = static_cast(-3333); + return __t ? hash<_Tp> {}(*__t) : __magic_disengaged_hash; + } + }; + + /// @} + +_GLIBCXX_END_NAMESPACE_VERSION +} // namespace std + +#endif // C++17 + +#endif // _GLIBCXX_OPTIONAL diff --git a/libstdc++-v3/testsuite/20_util/optional/assignment/1.cc b/libstdc++-v3/testsuite/20_util/optional/assignment/1.cc new file mode 100644 index 00000000000..25c62418b44 --- /dev/null +++ b/libstdc++-v3/testsuite/20_util/optional/assignment/1.cc @@ -0,0 +1,195 @@ +// { dg-options "-std=gnu++17" } +// { dg-do run } + +// Copyright (C) 2013-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 +// . + +#include +#include + +struct exception {}; + +int counter = 0; + +struct mixin_counter +{ + mixin_counter() { ++counter; } + mixin_counter(mixin_counter const&) { ++counter; } + ~mixin_counter() { --counter; } +}; + +struct value_type : private mixin_counter +{ + enum state_type + { + zero, + moved_from, + throwing_construction, + throwing_copy, + throwing_copy_assignment, + throwing_move, + throwing_move_assignment, + threw, + }; + + value_type() = default; + + explicit value_type(state_type state_) + : state(state_) + { + throw_if(throwing_construction); + } + + value_type(value_type const& other) + : state(other.state) + { + throw_if(throwing_copy); + } + + value_type& + operator=(value_type const& other) + { + state = other.state; + throw_if(throwing_copy_assignment); + return *this; + } + + value_type(value_type&& other) + : state(other.state) + { + other.state = moved_from; + throw_if(throwing_move); + } + + value_type& + operator=(value_type&& other) + { + state = other.state; + other.state = moved_from; + throw_if(throwing_move_assignment); + return *this; + } + + void throw_if(state_type match) + { + if(state == match) + { + state = threw; + throw exception {}; + } + } + + state_type state = zero; +}; + +int main() +{ + using O = std::optional; + using S = value_type::state_type; + auto const make = [](S s = S::zero) { return O { std::in_place, s }; }; + + enum outcome_type { nothrow, caught, bad_catch }; + + // Check copy/move assignment for disengaged optional + + // From disengaged optional + { + O o; + VERIFY( !o ); + O p; + o = p; + VERIFY( !o ); + VERIFY( !p ); + } + + { + O o; + VERIFY( !o ); + O p; + o = std::move(p); + VERIFY( !o ); + VERIFY( !p ); + } + + { + O o; + VERIFY( !o ); + o = {}; + VERIFY( !o ); + } + + // From engaged optional + { + O o; + VERIFY( !o ); + O p = make(S::throwing_copy_assignment); + o = p; + VERIFY( o && o->state == S::throwing_copy_assignment ); + VERIFY( p && p->state == S::throwing_copy_assignment ); + } + + { + O o; + VERIFY( !o ); + O p = make(S::throwing_move_assignment); + o = std::move(p); + VERIFY( o && o->state == S::throwing_move_assignment ); + VERIFY( p && p->state == S::moved_from ); + } + + { + outcome_type outcome {}; + O o; + VERIFY( !o ); + O p = make(S::throwing_copy); + + try + { + o = p; + } + catch(exception const&) + { outcome = caught; } + catch(...) + { outcome = bad_catch; } + + VERIFY( outcome == caught ); + VERIFY( !o ); + VERIFY( p && p->state == S::throwing_copy ); + } + + { + outcome_type outcome {}; + O o; + VERIFY( !o ); + O p = make(S::throwing_move); + + try + { + o = std::move(p); + } + catch(exception const&) + { outcome = caught; } + catch(...) + { outcome = bad_catch; } + + VERIFY( outcome == caught ); + VERIFY( !o ); + VERIFY( p && p->state == S::moved_from ); + } + + VERIFY( counter == 0 ); +} diff --git a/libstdc++-v3/testsuite/20_util/optional/assignment/2.cc b/libstdc++-v3/testsuite/20_util/optional/assignment/2.cc new file mode 100644 index 00000000000..d9d6ffab51f --- /dev/null +++ b/libstdc++-v3/testsuite/20_util/optional/assignment/2.cc @@ -0,0 +1,193 @@ +// { dg-options "-std=gnu++17" } +// { dg-do run } + +// Copyright (C) 2013-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 +// . + +#include +#include + +struct exception {}; + +int counter = 0; + +struct mixin_counter +{ + mixin_counter() { ++counter; } + mixin_counter(mixin_counter const&) { ++counter; } + ~mixin_counter() { --counter; } +}; + +struct value_type : private mixin_counter +{ + enum state_type + { + zero, + moved_from, + throwing_construction, + throwing_copy, + throwing_copy_assignment, + throwing_move, + throwing_move_assignment, + threw, + }; + + value_type() = default; + + explicit value_type(state_type state_) + : state(state_) + { + throw_if(throwing_construction); + } + + value_type(value_type const& other) + : state(other.state) + { + throw_if(throwing_copy); + } + + value_type& + operator=(value_type const& other) + { + state = other.state; + throw_if(throwing_copy_assignment); + return *this; + } + + value_type(value_type&& other) + : state(other.state) + { + other.state = moved_from; + throw_if(throwing_move); + } + + value_type& + operator=(value_type&& other) + { + state = other.state; + other.state = moved_from; + throw_if(throwing_move_assignment); + return *this; + } + + void throw_if(state_type match) + { + if(state == match) + { + state = threw; + throw exception {}; + } + } + + state_type state = zero; +}; + +int main() +{ + using O = std::optional; + using S = value_type::state_type; + auto const make = [](S s = S::zero) { return O { std::in_place, s }; }; + + enum outcome_type { nothrow, caught, bad_catch }; + + // Check copy/move assignment for engaged optional + + // From disengaged optional + { + O o = make(S::zero); + VERIFY( o ); + O p; + o = p; + VERIFY( !o ); + VERIFY( !p ); + } + + { + O o = make(S::zero); + VERIFY( o ); + O p; + o = std::move(p); + VERIFY( !o ); + VERIFY( !p ); + } + + { + O o = make(S::zero); + VERIFY( o ); + o = {}; + VERIFY( !o ); + } + + // From engaged optional + { + O o = make(S::zero); + VERIFY( o ); + O p = make(S::throwing_copy); + o = p; + VERIFY( o && o->state == S::throwing_copy); + VERIFY( p && p->state == S::throwing_copy); + } + + { + O o = make(S::zero); + VERIFY( o ); + O p = make(S::throwing_move); + o = std::move(p); + VERIFY( o && o->state == S::throwing_move); + VERIFY( p && p->state == S::moved_from); + } + + { + outcome_type outcome {}; + O o = make(S::zero); + VERIFY( o ); + O p = make(S::throwing_copy_assignment); + + try + { + o = p; + } + catch(exception const&) + { outcome = caught; } + catch(...) + { outcome = bad_catch; } + + VERIFY( o && o->state == S::threw); + VERIFY( p && p->state == S::throwing_copy_assignment); + } + + { + outcome_type outcome {}; + O o = make(S::zero); + VERIFY( o ); + O p = make(S::throwing_move_assignment); + + try + { + o = std::move(p); + } + catch(exception const&) + { outcome = caught; } + catch(...) + { outcome = bad_catch; } + + VERIFY( o && o->state == S::threw); + VERIFY( p && p->state == S::moved_from); + } + + VERIFY( counter == 0 ); +} diff --git a/libstdc++-v3/testsuite/20_util/optional/assignment/3.cc b/libstdc++-v3/testsuite/20_util/optional/assignment/3.cc new file mode 100644 index 00000000000..ce038b37cac --- /dev/null +++ b/libstdc++-v3/testsuite/20_util/optional/assignment/3.cc @@ -0,0 +1,158 @@ +// { dg-options "-std=gnu++17" } +// { dg-do run } + +// Copyright (C) 2013-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 +// . + +#include +#include + +struct exception {}; + +int counter = 0; + +struct mixin_counter +{ + mixin_counter() { ++counter; } + mixin_counter(mixin_counter const&) { ++counter; } + ~mixin_counter() { --counter; } +}; + +struct value_type : private mixin_counter +{ + enum state_type + { + zero, + moved_from, + throwing_construction, + throwing_copy, + throwing_copy_assignment, + throwing_move, + throwing_move_assignment, + threw, + }; + + value_type() = default; + + explicit value_type(state_type state_) + : state(state_) + { + throw_if(throwing_construction); + } + + value_type(value_type const& other) + : state(other.state) + { + throw_if(throwing_copy); + } + + value_type& + operator=(value_type const& other) + { + state = other.state; + throw_if(throwing_copy_assignment); + return *this; + } + + value_type(value_type&& other) + : state(other.state) + { + other.state = moved_from; + throw_if(throwing_move); + } + + value_type& + operator=(value_type&& other) + { + state = other.state; + other.state = moved_from; + throw_if(throwing_move_assignment); + return *this; + } + + void throw_if(state_type match) + { + if(state == match) + { + state = threw; + throw exception {}; + } + } + + state_type state = zero; +}; + +int main() +{ + using O = std::optional; + using S = value_type::state_type; + auto const make = [](S s = S::zero) { return value_type { s }; }; + + enum outcome_type { nothrow, caught, bad_catch }; + + // Check value assignment for disengaged optional + + { + O o; + value_type v = make(S::throwing_copy_assignment); + o = v; + VERIFY( o && o->state == S::throwing_copy_assignment ); + } + + { + O o; + value_type v = make(S::throwing_move_assignment); + o = std::move(v); + VERIFY( o && o->state == S::throwing_move_assignment ); + } + + { + outcome_type outcome {}; + O o; + value_type v = make(S::throwing_copy); + + try + { + o = v; + } + catch(exception const&) + { outcome = caught; } + catch(...) + { outcome = bad_catch; } + + VERIFY( !o ); + } + + { + outcome_type outcome {}; + O o; + value_type v = make(S::throwing_move); + + try + { + o = std::move(v); + } + catch(exception const&) + { outcome = caught; } + catch(...) + { outcome = bad_catch; } + + VERIFY( !o ); + } + + VERIFY( counter == 0 ); +} diff --git a/libstdc++-v3/testsuite/20_util/optional/assignment/4.cc b/libstdc++-v3/testsuite/20_util/optional/assignment/4.cc new file mode 100644 index 00000000000..7b972381831 --- /dev/null +++ b/libstdc++-v3/testsuite/20_util/optional/assignment/4.cc @@ -0,0 +1,158 @@ +// { dg-options "-std=gnu++17" } +// { dg-do run } + +// Copyright (C) 2013-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 +// . + +#include +#include + +struct exception {}; + +int counter = 0; + +struct mixin_counter +{ + mixin_counter() { ++counter; } + mixin_counter(mixin_counter const&) { ++counter; } + ~mixin_counter() { --counter; } +}; + +struct value_type : private mixin_counter +{ + enum state_type + { + zero, + moved_from, + throwing_construction, + throwing_copy, + throwing_copy_assignment, + throwing_move, + throwing_move_assignment, + threw, + }; + + value_type() = default; + + explicit value_type(state_type state_) + : state(state_) + { + throw_if(throwing_construction); + } + + value_type(value_type const& other) + : state(other.state) + { + throw_if(throwing_copy); + } + + value_type& + operator=(value_type const& other) + { + state = other.state; + throw_if(throwing_copy_assignment); + return *this; + } + + value_type(value_type&& other) + : state(other.state) + { + other.state = moved_from; + throw_if(throwing_move); + } + + value_type& + operator=(value_type&& other) + { + state = other.state; + other.state = moved_from; + throw_if(throwing_move_assignment); + return *this; + } + + void throw_if(state_type match) + { + if(state == match) + { + state = threw; + throw exception {}; + } + } + + state_type state = zero; +}; + +int main() +{ + using O = std::optional; + using S = value_type::state_type; + auto const make = [](S s = S::zero) { return value_type { s }; }; + + enum outcome_type { nothrow, caught, bad_catch }; + + // Check value assignment for engaged optional + + { + O o = make(); + value_type v = make(S::throwing_copy); + o = v; + VERIFY( o && o->state == S::throwing_copy); + } + + { + O o = make(); + value_type v = make(S::throwing_move); + o = std::move(v); + VERIFY( o && o->state == S::throwing_move); + } + + { + outcome_type outcome {}; + O o = make(); + value_type v = make(S::throwing_copy_assignment); + + try + { + o = v; + } + catch(exception const&) + { outcome = caught; } + catch(...) + { outcome = bad_catch; } + + VERIFY( o && o->state == S::threw ); + } + + { + outcome_type outcome {}; + O o = make(); + value_type v = make(S::throwing_move_assignment); + + try + { + o = std::move(v); + } + catch(exception const&) + { outcome = caught; } + catch(...) + { outcome = bad_catch; } + + VERIFY( o && o->state == S::threw ); + } + + VERIFY( counter == 0 ); +} diff --git a/libstdc++-v3/testsuite/20_util/optional/assignment/5.cc b/libstdc++-v3/testsuite/20_util/optional/assignment/5.cc new file mode 100644 index 00000000000..e450a461399 --- /dev/null +++ b/libstdc++-v3/testsuite/20_util/optional/assignment/5.cc @@ -0,0 +1,66 @@ +// { dg-options "-std=gnu++17" } +// { dg-do run } + +// Copyright (C) 2013-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 +// . + +#include +#include + +int counter = 0; + +struct mixin_counter +{ + mixin_counter() { ++counter; } + mixin_counter(mixin_counter const&) { ++counter; } + ~mixin_counter() { --counter; } +}; + +struct value_type : private mixin_counter { }; + +int main() +{ + using O = std::optional; + + // Check std::nullopt_t and 'default' (= {}) assignment + + { + O o; + o = std::nullopt; + VERIFY( !o ); + } + + { + O o { std::in_place }; + o = std::nullopt; + VERIFY( !o ); + } + + { + O o; + o = {}; + VERIFY( !o ); + } + + { + O o { std::in_place }; + o = {}; + VERIFY( !o ); + } + + VERIFY( counter == 0 ); +} diff --git a/libstdc++-v3/testsuite/20_util/optional/assignment/6.cc b/libstdc++-v3/testsuite/20_util/optional/assignment/6.cc new file mode 100644 index 00000000000..78e975bbe32 --- /dev/null +++ b/libstdc++-v3/testsuite/20_util/optional/assignment/6.cc @@ -0,0 +1,83 @@ +// { dg-options "-std=gnu++17" } +// { dg-do run } + +// Copyright (C) 2013-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 +// . + +#include +#include + +int counter = 0; + +struct mixin_counter +{ + mixin_counter() { ++counter; } + mixin_counter(mixin_counter const&) { ++counter; } + ~mixin_counter() { --counter; } +}; + +struct value_type : private mixin_counter +{ + value_type() = default; + value_type(int) : state(1) { } + value_type(std::initializer_list, const char*) : state(2) { } + int state = 0; +}; + +int main() +{ + using O = std::optional; + + // Check emplace + + { + O o; + o.emplace(); + VERIFY( o && o->state == 0 ); + } + { + O o { std::in_place, 0 }; + o.emplace(); + VERIFY( o && o->state == 0 ); + } + + { + O o; + o.emplace(0); + VERIFY( o && o->state == 1 ); + } + { + O o { std::in_place }; + o.emplace(0); + VERIFY( o && o->state == 1 ); + } + + { + O o; + o.emplace({ 'a' }, ""); + VERIFY( o && o->state == 2 ); + } + { + O o { std::in_place }; + o.emplace({ 'a' }, ""); + VERIFY( o && o->state == 2 ); + } + + static_assert( !std::is_constructible, int>(), "" ); + + VERIFY( counter == 0 ); +} diff --git a/libstdc++-v3/testsuite/20_util/optional/cons/copy.cc b/libstdc++-v3/testsuite/20_util/optional/cons/copy.cc new file mode 100644 index 00000000000..58f91768df4 --- /dev/null +++ b/libstdc++-v3/testsuite/20_util/optional/cons/copy.cc @@ -0,0 +1,126 @@ +// { dg-options "-std=gnu++17" } +// { dg-do run } + +// Copyright (C) 2013-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 copy of the GNU General Public License along +// with this library; see the file COPYING3. If not see +// . + +#include +#include + +struct tracker +{ + tracker(int value) : value(value) { ++count; } + ~tracker() { --count; } + + tracker(tracker const& other) : value(other.value) { ++count; } + tracker(tracker&& other) : value(other.value) + { + other.value = -1; + ++count; + } + + tracker& operator=(tracker const&) = default; + tracker& operator=(tracker&&) = default; + + int value; + + static int count; +}; + +int tracker::count = 0; + +struct exception { }; + +struct throwing_copy +{ + throwing_copy() = default; + throwing_copy(throwing_copy const&) { throw exception {}; } +}; + +int main() +{ + // [20.5.4.1] Constructors + + { + std::optional o; + auto copy = o; + VERIFY( !copy ); + VERIFY( !o ); + } + + { + const long val = 0x1234ABCD; + std::optional o { std::in_place, val}; + auto copy = o; + VERIFY( copy ); + VERIFY( *copy == val ); + VERIFY( o && o == val ); + } + + { + std::optional o; + auto copy = o; + VERIFY( !copy ); + VERIFY( tracker::count == 0 ); + VERIFY( !o ); + } + + { + std::optional o { std::in_place, 333 }; + auto copy = o; + VERIFY( copy ); + VERIFY( copy->value == 333 ); + VERIFY( tracker::count == 2 ); + VERIFY( o && o->value == 333 ); + } + + enum outcome { nothrow, caught, bad_catch }; + + { + outcome result = nothrow; + std::optional o; + + try + { + auto copy = o; + } + catch(exception const&) + { result = caught; } + catch(...) + { result = bad_catch; } + + VERIFY( result == nothrow ); + } + + { + outcome result = nothrow; + std::optional o { std::in_place }; + + try + { + auto copy = o; + } + catch(exception const&) + { result = caught; } + catch(...) + { result = bad_catch; } + + VERIFY( result == caught ); + } + + VERIFY( tracker::count == 0 ); +} diff --git a/libstdc++-v3/testsuite/20_util/optional/cons/default.cc b/libstdc++-v3/testsuite/20_util/optional/cons/default.cc new file mode 100644 index 00000000000..ebde86b807d --- /dev/null +++ b/libstdc++-v3/testsuite/20_util/optional/cons/default.cc @@ -0,0 +1,60 @@ +// { dg-options "-std=gnu++17" } +// { dg-do run } + +// Copyright (C) 2013-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 copy of the GNU General Public License along +// with this library; see the file COPYING3. If not see +// . + +#include +#include + +struct tracker +{ + tracker() { ++count; } + ~tracker() { --count; } + + tracker(tracker const&) { ++count; } + tracker(tracker&&) { ++count; } + + tracker& operator=(tracker const&) = default; + tracker& operator=(tracker&&) = default; + + static int count; +}; + +int tracker::count = 0; + +int main() +{ + // [20.5.4.1] Constructors + + { + std::optional o; + VERIFY( !o ); + } + + { + std::optional o {}; + VERIFY( !o ); + } + + { + std::optional o = {}; + VERIFY( !o ); + } + + VERIFY( tracker::count == 0 ); +} diff --git a/libstdc++-v3/testsuite/20_util/optional/cons/move.cc b/libstdc++-v3/testsuite/20_util/optional/cons/move.cc new file mode 100644 index 00000000000..54fd8c958e5 --- /dev/null +++ b/libstdc++-v3/testsuite/20_util/optional/cons/move.cc @@ -0,0 +1,126 @@ +// { dg-options "-std=gnu++17" } +// { dg-do run } + +// Copyright (C) 2013-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 +// . + +#include +#include + +struct tracker +{ + tracker(int value) : value(value) { ++count; } + ~tracker() { --count; } + + tracker(tracker const& other) : value(other.value) { ++count; } + tracker(tracker&& other) : value(other.value) + { + other.value = -1; + ++count; + } + + tracker& operator=(tracker const&) = default; + tracker& operator=(tracker&&) = default; + + int value; + + static int count; +}; + +int tracker::count = 0; + +struct exception { }; + +struct throwing_move +{ + throwing_move() = default; + throwing_move(throwing_move const&) { throw exception {}; } +}; + +int main() +{ + // [20.5.4.1] Constructors + + { + std::optional o; + auto moved_to = std::move(o); + VERIFY( !moved_to ); + VERIFY( !o ); + } + + { + const long val = 0x1234ABCD; + std::optional o { std::in_place, val}; + auto moved_to = std::move(o); + VERIFY( moved_to ); + VERIFY( *moved_to == val ); + VERIFY( o && *o == val ); + } + + { + std::optional o; + auto moved_to = std::move(o); + VERIFY( !moved_to ); + VERIFY( tracker::count == 0 ); + VERIFY( !o ); + } + + { + std::optional o { std::in_place, 333 }; + auto moved_to = std::move(o); + VERIFY( moved_to ); + VERIFY( moved_to->value == 333 ); + VERIFY( tracker::count == 2 ); + VERIFY( o && o->value == -1 ); + } + + enum outcome { nothrow, caught, bad_catch }; + + { + outcome result = nothrow; + std::optional o; + + try + { + auto moved_to = std::move(o); + } + catch(exception const&) + { result = caught; } + catch(...) + { result = bad_catch; } + + VERIFY( result == nothrow ); + } + + { + outcome result = nothrow; + std::optional o { std::in_place }; + + try + { + auto moved_to = std::move(o); + } + catch(exception const&) + { result = caught; } + catch(...) + { result = bad_catch; } + + VERIFY( result == caught ); + } + + VERIFY( tracker::count == 0 ); +} diff --git a/libstdc++-v3/testsuite/20_util/optional/cons/value.cc b/libstdc++-v3/testsuite/20_util/optional/cons/value.cc new file mode 100644 index 00000000000..13a6e9ca4dd --- /dev/null +++ b/libstdc++-v3/testsuite/20_util/optional/cons/value.cc @@ -0,0 +1,258 @@ +// { dg-options "-std=gnu++17" } +// { dg-do run } + +// Copyright (C) 2013-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 +// . + +#include +#include + +#include +#include + +struct tracker +{ + tracker(int value) : value(value) { ++count; } + ~tracker() { --count; } + + tracker(tracker const& other) : value(other.value) { ++count; } + tracker(tracker&& other) : value(other.value) + { + other.value = -1; + ++count; + } + + tracker& operator=(tracker const&) = default; + tracker& operator=(tracker&&) = default; + + int value; + + static int count; +}; + +int tracker::count = 0; + +struct exception { }; + +struct throwing_construction +{ + explicit throwing_construction(bool propagate) : propagate(propagate) { } + + throwing_construction(throwing_construction const& other) + : propagate(other.propagate) + { + if(propagate) + throw exception {}; + } + + bool propagate; +}; + +int main() +{ + // [20.5.4.1] Constructors + + { + auto i = 0x1234ABCD; + std::optional o { i }; + VERIFY( o ); + VERIFY( *o == 0x1234ABCD ); + VERIFY( i == 0x1234ABCD ); + } + + { + auto i = 0x1234ABCD; + std::optional o = i; + VERIFY( o ); + VERIFY( *o == 0x1234ABCD ); + VERIFY( i == 0x1234ABCD ); + } + + { + auto i = 0x1234ABCD; + std::optional o = { i }; + VERIFY( o ); + VERIFY( *o == 0x1234ABCD ); + VERIFY( i == 0x1234ABCD ); + } + + { + auto i = 0x1234ABCD; + std::optional o { std::move(i) }; + VERIFY( o ); + VERIFY( *o == 0x1234ABCD ); + VERIFY( i == 0x1234ABCD ); + } + + { + auto i = 0x1234ABCD; + std::optional o = std::move(i); + VERIFY( o ); + VERIFY( *o == 0x1234ABCD ); + VERIFY( i == 0x1234ABCD ); + } + + { + auto i = 0x1234ABCD; + std::optional o = { std::move(i) }; + VERIFY( o ); + VERIFY( *o == 0x1234ABCD ); + VERIFY( i == 0x1234ABCD ); + } + + { + std::vector v = { 0, 1, 2, 3, 4, 5 }; + std::optional> o { v }; + VERIFY( !v.empty() ); + VERIFY( o->size() == 6 ); + } + + { + std::vector v = { 0, 1, 2, 3, 4, 5 }; + std::optional> o = v; + VERIFY( !v.empty() ); + VERIFY( o->size() == 6 ); + } + + { + std::vector v = { 0, 1, 2, 3, 4, 5 }; + std::optional> o { v }; + VERIFY( !v.empty() ); + VERIFY( o->size() == 6 ); + } + + { + std::vector v = { 0, 1, 2, 3, 4, 5 }; + std::optional> o { std::move(v) }; + VERIFY( v.empty() ); + VERIFY( o->size() == 6 ); + } + + { + std::vector v = { 0, 1, 2, 3, 4, 5 }; + std::optional> o = std::move(v); + VERIFY( v.empty() ); + VERIFY( o->size() == 6 ); + } + + { + std::vector v = { 0, 1, 2, 3, 4, 5 }; + std::optional> o { std::move(v) }; + VERIFY( v.empty() ); + VERIFY( o->size() == 6 ); + } + + { + tracker t { 333 }; + std::optional o = t; + VERIFY( o->value == 333 ); + VERIFY( tracker::count == 2 ); + VERIFY( t.value == 333 ); + } + + { + tracker t { 333 }; + std::optional o = std::move(t); + VERIFY( o->value == 333 ); + VERIFY( tracker::count == 2 ); + VERIFY( t.value == -1 ); + } + + enum outcome { nothrow, caught, bad_catch }; + + { + outcome result = nothrow; + throwing_construction t { false }; + + try + { + std::optional o { t }; + } + catch(exception const&) + { result = caught; } + catch(...) + { result = bad_catch; } + + VERIFY( result == nothrow ); + } + + { + outcome result = nothrow; + throwing_construction t { true }; + + try + { + std::optional o { t }; + } + catch(exception const&) + { result = caught; } + catch(...) + { result = bad_catch; } + + VERIFY( result == caught ); + } + + { + outcome result = nothrow; + throwing_construction t { false }; + + try + { + std::optional o { std::move(t) }; + } + catch(exception const&) + { result = caught; } + catch(...) + { result = bad_catch; } + + VERIFY( result == nothrow ); + } + + { + outcome result = nothrow; + throwing_construction t { true }; + + try + { + std::optional o { std::move(t) }; + } + catch(exception const&) + { result = caught; } + catch(...) + { result = bad_catch; } + + VERIFY( result == caught ); + } + + { + std::optional os = "foo"; + struct X + { + explicit X(int) {} + X& operator=(int) {return *this;} + }; + std::optional ox{42}; + std::optional oi{42}; + std::optional ox2{oi}; + std::optional os2; + os2 = "foo"; + std::optional ox3; + ox3 = 42; + std::optional ox4; + ox4 = oi; + } +} diff --git a/libstdc++-v3/testsuite/20_util/optional/cons/value_neg.cc b/libstdc++-v3/testsuite/20_util/optional/cons/value_neg.cc new file mode 100644 index 00000000000..4bf5dcc4ec2 --- /dev/null +++ b/libstdc++-v3/testsuite/20_util/optional/cons/value_neg.cc @@ -0,0 +1,39 @@ +// { dg-options "-std=gnu++17" } +// { dg-do compile } + +// Copyright (C) 2013-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 +// . + +#include +#include + +#include +#include + +int main() +{ + { + struct X + { + explicit X(int) {} + }; + std::optional ox{42}; + std::optional ox2 = 42; // { dg-error "conversion" } + std::optional> oup{new int}; + std::optional> oup2 = new int; // { dg-error "conversion" } + } +} diff --git a/libstdc++-v3/testsuite/20_util/optional/constexpr/cons/default.cc b/libstdc++-v3/testsuite/20_util/optional/constexpr/cons/default.cc new file mode 100644 index 00000000000..ae523dfbc16 --- /dev/null +++ b/libstdc++-v3/testsuite/20_util/optional/constexpr/cons/default.cc @@ -0,0 +1,42 @@ +// { dg-options "-std=gnu++17" } +// { dg-do compile } + +// Copyright (C) 2013-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 copy of the GNU General Public License along +// with this library; see the file COPYING3. If not see +// . + +#include +#include + +int main() +{ + // [20.5.4.1] Constructors + + { + constexpr std::optional o; + static_assert( !o, "" ); + } + + { + constexpr std::optional o {}; + static_assert( !o, "" ); + } + + { + constexpr std::optional o = {}; + static_assert( !o, "" ); + } +} diff --git a/libstdc++-v3/testsuite/20_util/optional/constexpr/cons/value.cc b/libstdc++-v3/testsuite/20_util/optional/constexpr/cons/value.cc new file mode 100644 index 00000000000..de7744d3dc8 --- /dev/null +++ b/libstdc++-v3/testsuite/20_util/optional/constexpr/cons/value.cc @@ -0,0 +1,69 @@ +// { dg-options "-std=gnu++17" } +// { dg-do compile } + +// Copyright (C) 2013-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 +// . + +#include +#include + +int main() +{ + // [20.5.4.1] Constructors + + { + constexpr long i = 0x1234ABCD; + constexpr std::optional o { i }; + static_assert( o, "" ); + static_assert( *o == 0x1234ABCD, "" ); + } + + { + constexpr long i = 0x1234ABCD; + constexpr std::optional o = i; + static_assert( o, "" ); + static_assert( *o == 0x1234ABCD, "" ); + } + + { + constexpr long i = 0x1234ABCD; + constexpr std::optional o = { i }; + static_assert( o, "" ); + static_assert( *o == 0x1234ABCD, "" ); + } + + { + constexpr long i = 0x1234ABCD; + constexpr std::optional o { std::move(i) }; + static_assert( o, "" ); + static_assert( *o == 0x1234ABCD, "" ); + } + + { + constexpr long i = 0x1234ABCD; + constexpr std::optional o = std::move(i); + static_assert( o, "" ); + static_assert( *o == 0x1234ABCD, "" ); + } + + { + constexpr long i = 0x1234ABCD; + constexpr std::optional o = { std::move(i) }; + static_assert( o, "" ); + static_assert( *o == 0x1234ABCD, "" ); + } +} diff --git a/libstdc++-v3/testsuite/20_util/optional/constexpr/in_place.cc b/libstdc++-v3/testsuite/20_util/optional/constexpr/in_place.cc new file mode 100644 index 00000000000..cd75275aaff --- /dev/null +++ b/libstdc++-v3/testsuite/20_util/optional/constexpr/in_place.cc @@ -0,0 +1,43 @@ +// { dg-options "-std=gnu++17" } +// { dg-do compile } + +// Copyright (C) 2013-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 copy of the GNU General Public License along +// with this library; see the file COPYING3. If not see +// . + +#include +#include + +int main() +{ + // [20.5.5] In-place construction + static_assert( std::is_same(), "" ); + static_assert( std::is_empty(), "" ); + + { + constexpr std::optional o { std::in_place }; + static_assert( o, "" ); + static_assert( *o == int {}, "" ); + + static_assert( !std::is_convertible>(), "" ); + } + + { + constexpr std::optional o { std::in_place, 42 }; + static_assert( o, "" ); + static_assert( *o == 42, "" ); + } +} diff --git a/libstdc++-v3/testsuite/20_util/optional/constexpr/make_optional.cc b/libstdc++-v3/testsuite/20_util/optional/constexpr/make_optional.cc new file mode 100644 index 00000000000..44ee654a07b --- /dev/null +++ b/libstdc++-v3/testsuite/20_util/optional/constexpr/make_optional.cc @@ -0,0 +1,30 @@ +// { dg-options "-std=gnu++17" } + +// Copyright (C) 2013-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 +// . + +#include +#include + +int main() +{ + constexpr int i = 42; + constexpr auto o = std::make_optional(i); + static_assert( std::is_same>(), "" ); + static_assert( o && *o == 42, "" ); + static_assert( &*o != &i, "" ); +} diff --git a/libstdc++-v3/testsuite/20_util/optional/constexpr/nullopt.cc b/libstdc++-v3/testsuite/20_util/optional/constexpr/nullopt.cc new file mode 100644 index 00000000000..61fddefa5a4 --- /dev/null +++ b/libstdc++-v3/testsuite/20_util/optional/constexpr/nullopt.cc @@ -0,0 +1,46 @@ +// { dg-options "-std=gnu++17" } +// { dg-do compile } + +// Copyright (C) 2013-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 copy of the GNU General Public License along +// with this library; see the file COPYING3. If not see +// . + +#include +#include + +int main() +{ + // [20.5.6] Disengaged state indicator + static_assert( std::is_same(), "" ); + static_assert( std::is_empty(), "" ); + static_assert( std::is_literal_type(), "" ); + static_assert( !std::is_default_constructible(), "" ); + + { + constexpr std::optional o = std::nullopt; + static_assert( !o, "" ); + } + + { + constexpr std::optional o = { std::nullopt }; + static_assert( !o, "" ); + } + + { + constexpr std::optional o { std::nullopt }; + static_assert( !o, "" ); + } +} diff --git a/libstdc++-v3/testsuite/20_util/optional/constexpr/observers/1.cc b/libstdc++-v3/testsuite/20_util/optional/constexpr/observers/1.cc new file mode 100644 index 00000000000..6c06f089ec2 --- /dev/null +++ b/libstdc++-v3/testsuite/20_util/optional/constexpr/observers/1.cc @@ -0,0 +1,32 @@ +// { dg-options "-std=gnu++17" } +// { dg-do compile } + +// Copyright (C) 2013-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 +// . + +#include + +struct value_type +{ + int i; +}; + +int main() +{ + constexpr std::optional o { value_type { 51 } }; + static_assert( (*o).i == 51, "" ); +} diff --git a/libstdc++-v3/testsuite/20_util/optional/constexpr/observers/2.cc b/libstdc++-v3/testsuite/20_util/optional/constexpr/observers/2.cc new file mode 100644 index 00000000000..11363af32cb --- /dev/null +++ b/libstdc++-v3/testsuite/20_util/optional/constexpr/observers/2.cc @@ -0,0 +1,35 @@ +// { dg-options "-std=gnu++17" } + +// Copyright (C) 2013-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 +// . + +#include + +struct value_type +{ + int i; + + void* operator&() { return nullptr; } // N.B. non-const +}; + +int main() +{ + constexpr std::optional o { value_type { 51 } }; + static_assert( o->i == 51, "" ); + static_assert( o->i == (*o).i, "" ); + static_assert( &o->i == &(*o).i, "" ); +} diff --git a/libstdc++-v3/testsuite/20_util/optional/constexpr/observers/3.cc b/libstdc++-v3/testsuite/20_util/optional/constexpr/observers/3.cc new file mode 100644 index 00000000000..118fea92087 --- /dev/null +++ b/libstdc++-v3/testsuite/20_util/optional/constexpr/observers/3.cc @@ -0,0 +1,33 @@ +// { dg-options "-std=gnu++17" } + +// Copyright (C) 2013-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 +// . + +#include + +struct value_type +{ + int i; +}; + +int main() +{ + constexpr std::optional o { value_type { 51 } }; + static_assert( o.value().i == 51, "" ); + static_assert( o.value().i == (*o).i, "" ); + static_assert( &o.value().i == &(*o).i, "" ); +} diff --git a/libstdc++-v3/testsuite/20_util/optional/constexpr/observers/4.cc b/libstdc++-v3/testsuite/20_util/optional/constexpr/observers/4.cc new file mode 100644 index 00000000000..3e6436c6db1 --- /dev/null +++ b/libstdc++-v3/testsuite/20_util/optional/constexpr/observers/4.cc @@ -0,0 +1,34 @@ +// { dg-options "-std=gnu++17" } +// { dg-do compile } + +// Copyright (C) 2013-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 +// . + +#include + +struct value_type +{ + int i; +}; + +int main() +{ + constexpr std::optional o { value_type { 51 } }; + constexpr value_type fallback { 3 }; + static_assert( o.value_or(fallback).i == 51, "" ); + static_assert( o.value_or(fallback).i == (*o).i, "" ); +} diff --git a/libstdc++-v3/testsuite/20_util/optional/constexpr/observers/5.cc b/libstdc++-v3/testsuite/20_util/optional/constexpr/observers/5.cc new file mode 100644 index 00000000000..15ac84b25ee --- /dev/null +++ b/libstdc++-v3/testsuite/20_util/optional/constexpr/observers/5.cc @@ -0,0 +1,39 @@ +// { dg-options "-std=gnu++17" } +// { dg-do compile } + +// Copyright (C) 2013-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 +// . + +#include + +struct value_type +{ + int i; +}; + +int main() +{ + { + constexpr std::optional o = std::nullopt; + static_assert( !o, "" ); + } + + { + constexpr std::optional o { value_type { 51 } }; + static_assert( o, "" ); + } +} diff --git a/libstdc++-v3/testsuite/20_util/optional/constexpr/relops/1.cc b/libstdc++-v3/testsuite/20_util/optional/constexpr/relops/1.cc new file mode 100644 index 00000000000..c948e170125 --- /dev/null +++ b/libstdc++-v3/testsuite/20_util/optional/constexpr/relops/1.cc @@ -0,0 +1,99 @@ +// { dg-options "-std=gnu++17" } +// { dg-do compile } + +// Copyright (C) 2013-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 +// . + +#include +#include + +namespace ns +{ + struct value_type + { + int i; + const char* s; + }; + + constexpr bool + strcmp(const char* lhs, const char* rhs) + { + return *lhs == *rhs && (!*lhs || strcmp(lhs + 1, rhs + 1)); + } + + constexpr bool + strrel(const char* lhs, const char* rhs) + { + return (*rhs && (!*lhs || (*lhs < *rhs))) + || ((*lhs && *rhs && !(*rhs < *lhs)) && strrel(lhs + 1, rhs + 1)); + } + + constexpr bool + operator==(value_type const& lhs, value_type const& rhs) + { return (lhs.i == rhs.i) && strcmp(lhs.s, rhs.s); } + + constexpr bool + operator!=(value_type const& lhs, value_type const& rhs) + { return !(lhs == rhs); } + + constexpr bool + operator<(value_type const& lhs, value_type const& rhs) + { return (lhs.i < rhs.i) || (!(rhs.i < lhs.i) && strrel(lhs.s, rhs.s)); } + +} // namespace ns + +int main() +{ + using ns::value_type; + using O = std::optional; + + { + constexpr O o, p; + static_assert( o == p, "" ); + static_assert( !(o != p), "" ); + } + + { + constexpr O o { value_type { 42, "forty-two" } }, p; + static_assert( !(o == p), "" ); + static_assert( o != p, "" ); + } + + { + constexpr O o, p { value_type { 42, "forty-two" } }; + static_assert( !(o == p), "" ); + static_assert( o != p, "" ); + } + + { + constexpr O o { value_type { 11, "eleventy" } }, p { value_type { 42, "forty-two" } }; + static_assert( !(o == p), "" ); + static_assert( o != p, "" ); + } + + { + constexpr O o { value_type { 42, "forty-two" } }, p { value_type { 11, "eleventy" } }; + static_assert( !(o == p), "" ); + static_assert( o != p, "" ); + } + + { + constexpr O o { value_type { 42, "forty-two" } }, p { value_type { 42, "forty-two" } }; + static_assert( o == p, "" ); + static_assert( !(o != p), "" ); + } +} diff --git a/libstdc++-v3/testsuite/20_util/optional/constexpr/relops/2.cc b/libstdc++-v3/testsuite/20_util/optional/constexpr/relops/2.cc new file mode 100644 index 00000000000..9aa9273255b --- /dev/null +++ b/libstdc++-v3/testsuite/20_util/optional/constexpr/relops/2.cc @@ -0,0 +1,111 @@ +// { dg-options "-std=gnu++17" } +// { dg-do compile } + +// Copyright (C) 2013-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 +// . + +#include +#include + +namespace ns +{ + struct value_type + { + int i; + const char* s; + }; + + constexpr bool + strcmp(const char* lhs, const char* rhs) + { + return *lhs == *rhs && (!*lhs || strcmp(lhs + 1, rhs + 1)); + } + + constexpr bool + strrel(const char* lhs, const char* rhs) + { + return (*rhs && (!*lhs || (*lhs < *rhs))) + || ((*lhs && *rhs && !(*rhs < *lhs)) && strrel(lhs + 1, rhs + 1)); + } + + constexpr bool + operator==(value_type const& lhs, value_type const& rhs) + { return (lhs.i == rhs.i) && strcmp(lhs.s, rhs.s); } + + constexpr bool + operator!=(value_type const& lhs, value_type const& rhs) + { return !(lhs == rhs); } + + constexpr bool + operator<(value_type const& lhs, value_type const& rhs) + { return (lhs.i < rhs.i) || (!(rhs.i < lhs.i) && strrel(lhs.s, rhs.s)); } + +} // namespace ns + +int main() +{ + using ns::value_type; + using O = std::optional; + + { + constexpr O o, p; + static_assert( !(o < p), "" ); + static_assert( !(o > p), "" ); + static_assert( o <= p, "" ); + static_assert( o >= p, "" ); + } + + { + constexpr O o { value_type { 42, "forty-two" } }, p; + static_assert( !(o < p), "" ); + static_assert( o > p, "" ); + static_assert( !(o <= p), "" ); + static_assert( o >= p, "" ); + } + + { + constexpr O o, p { value_type { 42, "forty-two" } }; + static_assert( o < p, "" ); + static_assert( !(o > p), "" ); + static_assert( o <= p, "" ); + static_assert( !(o >= p), "" ); + } + + { + constexpr O o { value_type { 11, "eleventy" } }, p { value_type { 42, "forty-two" } }; + static_assert( o < p, "" ); + static_assert( !(o > p), "" ); + static_assert( o <= p, "" ); + static_assert( !(o >= p), "" ); + } + + { + constexpr O o { value_type { 42, "forty-two" } }, p { value_type { 11, "eleventy" } }; + static_assert( !(o < p), "" ); + static_assert( o > p, "" ); + static_assert( !(o <= p), "" ); + static_assert( o >= p, "" ); + } + + { + constexpr O o { value_type { 42, "forty-two" } }, p { value_type { 42, "forty-two" } }; + static_assert( !(o < p), "" ); + static_assert( !(o > p), "" ); + static_assert( o <= p, "" ); + static_assert( o >= p, "" ); + } +} diff --git a/libstdc++-v3/testsuite/20_util/optional/constexpr/relops/3.cc b/libstdc++-v3/testsuite/20_util/optional/constexpr/relops/3.cc new file mode 100644 index 00000000000..eb34f796399 --- /dev/null +++ b/libstdc++-v3/testsuite/20_util/optional/constexpr/relops/3.cc @@ -0,0 +1,89 @@ +// { dg-options "-std=gnu++17" } +// { dg-do compile } + +// Copyright (C) 2013-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 +// . + +#include +#include + +namespace ns +{ + struct value_type + { + int i; + const char* s; + }; + + constexpr bool + strcmp(const char* lhs, const char* rhs) + { + return *lhs == *rhs && (!*lhs || strcmp(lhs + 1, rhs + 1)); + } + + constexpr bool + strrel(const char* lhs, const char* rhs) + { + return (*rhs && (!*lhs || (*lhs < *rhs))) + || ((*lhs && *rhs && !(*rhs < *lhs)) && strrel(lhs + 1, rhs + 1)); + } + + constexpr bool + operator==(value_type const& lhs, value_type const& rhs) + { return (lhs.i == rhs.i) && strcmp(lhs.s, rhs.s); } + + constexpr bool + operator!=(value_type const& lhs, value_type const& rhs) + { return !(lhs == rhs); } + + constexpr bool + operator<(value_type const& lhs, value_type const& rhs) + { return (lhs.i < rhs.i) || (!(rhs.i < lhs.i) && strrel(lhs.s, rhs.s)); } + +} // namespace ns + +int main() +{ + using ns::value_type; + using O = std::optional; + + constexpr value_type reference { 42, "forty-two" }; + + { + constexpr O o; + static_assert( !(o == reference), "" ); + static_assert( !(reference == o), "" ); + static_assert( o != reference, "" ); + static_assert( reference != o, "" ); + } + + { + constexpr O o { value_type { 11, "eleventy" } }; + static_assert( !(o == reference), "" ); + static_assert( !(reference == o), "" ); + static_assert( o != reference, "" ); + static_assert( reference != o, "" ); + } + + { + constexpr O o { value_type { 42, "forty-two" } }; + static_assert( o == reference, "" ); + static_assert( reference == o, "" ); + static_assert( !(o != reference), "" ); + static_assert( !(reference != o), "" ); + } +} diff --git a/libstdc++-v3/testsuite/20_util/optional/constexpr/relops/4.cc b/libstdc++-v3/testsuite/20_util/optional/constexpr/relops/4.cc new file mode 100644 index 00000000000..15130d4efbd --- /dev/null +++ b/libstdc++-v3/testsuite/20_util/optional/constexpr/relops/4.cc @@ -0,0 +1,101 @@ +// { dg-options "-std=gnu++17" } +// { dg-do compile } + +// Copyright (C) 2013-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 +// . + +#include +#include + +namespace ns +{ + struct value_type + { + int i; + const char* s; + }; + + constexpr bool + strcmp(const char* lhs, const char* rhs) + { + return *lhs == *rhs && (!*lhs || strcmp(lhs + 1, rhs + 1)); + } + + constexpr bool + strrel(const char* lhs, const char* rhs) + { + return (*rhs && (!*lhs || (*lhs < *rhs))) + || ((*lhs && *rhs && !(*rhs < *lhs)) && strrel(lhs + 1, rhs + 1)); + } + + constexpr bool + operator==(value_type const& lhs, value_type const& rhs) + { return (lhs.i == rhs.i) && strcmp(lhs.s, rhs.s); } + + constexpr bool + operator!=(value_type const& lhs, value_type const& rhs) + { return !(lhs == rhs); } + + constexpr bool + operator<(value_type const& lhs, value_type const& rhs) + { return (lhs.i < rhs.i) || (!(rhs.i < lhs.i) && strrel(lhs.s, rhs.s)); } + +} // namespace ns + +int main() +{ + using ns::value_type; + using O = std::optional; + + constexpr value_type reference { 42, "forty-two" }; + + { + constexpr O o; + static_assert( o < reference, "" ); + static_assert( !(reference < o), "" ); + static_assert( !(o > reference), "" ); + static_assert( reference > o, "" ); + static_assert( o <= reference, "" ); + static_assert( !(reference <= o), "" ); + static_assert( !(o >= reference), "" ); + static_assert( reference >= o, "" ); + } + + { + constexpr O o { value_type { 11, "eleventy" } }; + static_assert( o < reference, "" ); + static_assert( !(reference < o), "" ); + static_assert( !(o > reference), "" ); + static_assert( reference > o, "" ); + static_assert( o <= reference, "" ); + static_assert( !(reference <= o), "" ); + static_assert( !(o >= reference), "" ); + static_assert( reference >= o, "" ); + } + + { + constexpr O o { value_type { 42, "forty-two" } }; + static_assert( !(o < reference), "" ); + static_assert( !(reference < o), "" ); + static_assert( !(o > reference), "" ); + static_assert( !(reference > o), "" ); + static_assert( o <= reference, "" ); + static_assert( reference <= o, "" ); + static_assert( o >= reference, "" ); + static_assert( reference >= o, "" ); + } +} diff --git a/libstdc++-v3/testsuite/20_util/optional/constexpr/relops/5.cc b/libstdc++-v3/testsuite/20_util/optional/constexpr/relops/5.cc new file mode 100644 index 00000000000..99a208208bc --- /dev/null +++ b/libstdc++-v3/testsuite/20_util/optional/constexpr/relops/5.cc @@ -0,0 +1,80 @@ +// { dg-options "-std=gnu++17" } +// { dg-do compile } + +// Copyright (C) 2013-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 +// . + +#include +#include + +namespace ns +{ + struct value_type + { + int i; + const char* s; + }; + + constexpr bool + strcmp(const char* lhs, const char* rhs) + { + return *lhs == *rhs && (!*lhs || strcmp(lhs + 1, rhs + 1)); + } + + constexpr bool + strrel(const char* lhs, const char* rhs) + { + return (*rhs && (!*lhs || (*lhs < *rhs))) + || ((*lhs && *rhs && !(*rhs < *lhs)) && strrel(lhs + 1, rhs + 1)); + } + + constexpr bool + operator==(value_type const& lhs, value_type const& rhs) + { return (lhs.i == rhs.i) && strcmp(lhs.s, rhs.s); } + + constexpr bool + operator!=(value_type const& lhs, value_type const& rhs) + { return !(lhs == rhs); } + + constexpr bool + operator<(value_type const& lhs, value_type const& rhs) + { return (lhs.i < rhs.i) || (!(rhs.i < lhs.i) && strrel(lhs.s, rhs.s)); } + +} // namespace ns + +int main() +{ + using ns::value_type; + using O = std::optional; + using std::nullopt; + + { + constexpr O o; + static_assert( o == nullopt, "" ); + static_assert( nullopt == o, "" ); + static_assert( !(o != nullopt), "" ); + static_assert( !(nullopt != o), "" ); + } + + { + constexpr O o { std::in_place }; + static_assert( !(o == nullopt), "" ); + static_assert( !(nullopt == o), "" ); + static_assert( o != nullopt, "" ); + static_assert( nullopt != o, "" ); + } +} diff --git a/libstdc++-v3/testsuite/20_util/optional/constexpr/relops/6.cc b/libstdc++-v3/testsuite/20_util/optional/constexpr/relops/6.cc new file mode 100644 index 00000000000..7337287852b --- /dev/null +++ b/libstdc++-v3/testsuite/20_util/optional/constexpr/relops/6.cc @@ -0,0 +1,88 @@ +// { dg-options "-std=gnu++17" } +// { dg-do compile } + +// Copyright (C) 2013-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 +// . + +#include +#include + +namespace ns +{ + struct value_type + { + int i; + const char* s; + }; + + constexpr bool + strcmp(const char* lhs, const char* rhs) + { + return *lhs == *rhs && (!*lhs || strcmp(lhs + 1, rhs + 1)); + } + + constexpr bool + strrel(const char* lhs, const char* rhs) + { + return (*rhs && (!*lhs || (*lhs < *rhs))) + || ((*lhs && *rhs && !(*rhs < *lhs)) && strrel(lhs + 1, rhs + 1)); + } + + constexpr bool + operator==(value_type const& lhs, value_type const& rhs) + { return (lhs.i == rhs.i) && strcmp(lhs.s, rhs.s); } + + constexpr bool + operator!=(value_type const& lhs, value_type const& rhs) + { return !(lhs == rhs); } + + constexpr bool + operator<(value_type const& lhs, value_type const& rhs) + { return (lhs.i < rhs.i) || (!(rhs.i < lhs.i) && strrel(lhs.s, rhs.s)); } + +} // namespace ns + +int main() +{ + using ns::value_type; + using O = std::optional; + using std::nullopt; + + { + constexpr O o; + static_assert( !(o < nullopt), "" ); + static_assert( !(nullopt < o), "" ); + static_assert( !(o > nullopt), "" ); + static_assert( !(nullopt > o), "" ); + static_assert( o <= nullopt, "" ); + static_assert( nullopt <= o, "" ); + static_assert( o >= nullopt, "" ); + static_assert( nullopt >= o, "" ); + } + + { + constexpr O o { std::in_place }; + static_assert( !(o < nullopt), "" ); + static_assert( nullopt < o, "" ); + static_assert( o > nullopt, "" ); + static_assert( !(nullopt > o), "" ); + static_assert( !(o <= nullopt), "" ); + static_assert( nullopt <= o, "" ); + static_assert( o >= nullopt, "" ); + static_assert( !(nullopt >= o), "" ); + } +} diff --git a/libstdc++-v3/testsuite/20_util/optional/in_place.cc b/libstdc++-v3/testsuite/20_util/optional/in_place.cc new file mode 100644 index 00000000000..ef8c744f1dc --- /dev/null +++ b/libstdc++-v3/testsuite/20_util/optional/in_place.cc @@ -0,0 +1,66 @@ +// { dg-options "-std=gnu++17" } +// { dg-do run } + +// Copyright (C) 2013-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 copy of the GNU General Public License along +// with this library; see the file COPYING3. If not see +// . + +#include +#include + +#include + +int main() +{ + // [20.5.5] In-place construction + static_assert( std::is_same(), "" ); + static_assert( std::is_empty(), "" ); + + { + std::optional o { std::in_place }; + VERIFY( o ); + VERIFY( *o == int() ); + + static_assert( !std::is_convertible>(), "" ); + } + + { + std::optional o { std::in_place, 42 }; + VERIFY( o ); + VERIFY( *o == 42 ); + } + + { + std::optional> o { std::in_place, 18, 4 }; + VERIFY( o ); + VERIFY( o->size() == 18 ); + VERIFY( (*o)[17] == 4 ); + } + + { + std::optional> o { std::in_place, { 18, 4 } }; + VERIFY( o ); + VERIFY( o->size() == 2 ); + VERIFY( (*o)[0] == 18 ); + } + + { + std::optional> o { std::in_place, { 18, 4 }, std::allocator {} }; + VERIFY( o ); + VERIFY( o->size() == 2 ); + VERIFY( (*o)[0] == 18 ); + } +} diff --git a/libstdc++-v3/testsuite/20_util/optional/make_optional.cc b/libstdc++-v3/testsuite/20_util/optional/make_optional.cc new file mode 100644 index 00000000000..6f245c716ad --- /dev/null +++ b/libstdc++-v3/testsuite/20_util/optional/make_optional.cc @@ -0,0 +1,31 @@ +// { dg-options "-std=gnu++17" } +// { dg-do run } + +// Copyright (C) 2013-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 +// . + +#include +#include + +int main() +{ + const int i = 42; + auto o = std::make_optional(i); + static_assert( std::is_same>(), "" ); + VERIFY( o && *o == 42 ); + VERIFY( &*o != &i ); +} diff --git a/libstdc++-v3/testsuite/20_util/optional/nullopt.cc b/libstdc++-v3/testsuite/20_util/optional/nullopt.cc new file mode 100644 index 00000000000..f9ee748b9c2 --- /dev/null +++ b/libstdc++-v3/testsuite/20_util/optional/nullopt.cc @@ -0,0 +1,46 @@ +// { dg-options "-std=gnu++17" } +// { dg-do run } + +// Copyright (C) 2013-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 copy of the GNU General Public License along +// with this library; see the file COPYING3. If not see +// . + +#include +#include + +int main() +{ + // [20.5.6] Disengaged state indicator + static_assert( std::is_same(), "" ); + static_assert( std::is_empty(), "" ); + static_assert( std::is_literal_type(), "" ); + static_assert( !std::is_default_constructible(), "" ); + + { + std::optional o = std::nullopt; + VERIFY( !o ); + } + + { + std::optional o = { std::nullopt }; + VERIFY( !o ); + } + + { + std::optional o { std::nullopt }; + VERIFY( !o ); + } +} diff --git a/libstdc++-v3/testsuite/20_util/optional/observers/1.cc b/libstdc++-v3/testsuite/20_util/optional/observers/1.cc new file mode 100644 index 00000000000..ba10bce7119 --- /dev/null +++ b/libstdc++-v3/testsuite/20_util/optional/observers/1.cc @@ -0,0 +1,33 @@ +// { dg-options "-std=gnu++17" } +// { dg-do run } + +// Copyright (C) 2013-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 +// . + +#include +#include + +struct value_type +{ + int i; +}; + +int main() +{ + std::optional o { value_type { 51 } }; + VERIFY( (*o).i == 51 ); +} diff --git a/libstdc++-v3/testsuite/20_util/optional/observers/2.cc b/libstdc++-v3/testsuite/20_util/optional/observers/2.cc new file mode 100644 index 00000000000..d3799b9214a --- /dev/null +++ b/libstdc++-v3/testsuite/20_util/optional/observers/2.cc @@ -0,0 +1,37 @@ +// { dg-options "-std=gnu++17" } +// { dg-do run } + +// Copyright (C) 2013-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 +// . + +#include +#include + +struct value_type +{ + int i; +}; + +void* operator&(const value_type&) = delete; + +int main() +{ + std::optional o { value_type { 51 } }; + VERIFY( o->i == 51 ); + VERIFY( o->i == (*o).i ); + VERIFY( &o->i == &(*o).i ); +} diff --git a/libstdc++-v3/testsuite/20_util/optional/observers/3.cc b/libstdc++-v3/testsuite/20_util/optional/observers/3.cc new file mode 100644 index 00000000000..9ad5d01ae42 --- /dev/null +++ b/libstdc++-v3/testsuite/20_util/optional/observers/3.cc @@ -0,0 +1,58 @@ +// { dg-options "-std=gnu++17" } +// { dg-do run } + +// Copyright (C) 2013-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 +// . + +#include +#include + +struct value_type +{ + int i; +}; + +int main() +{ + { + std::optional o { value_type { 51 } }; + VERIFY( o.value().i == 51 ); + VERIFY( o.value().i == (*o).i ); + VERIFY( &o.value().i == &(*o).i ); + } + + { + enum outcome_type { nothrow, caught, bad_catch }; + + outcome_type outcome {}; + std::optional o = std::nullopt; + bool called = false; + auto const eat = [&called](int) { called = true; }; + + try + { + eat(o.value().i); + } + catch(std::bad_optional_access const&) + { outcome = caught; } + catch(...) + { outcome = bad_catch; } + + VERIFY( outcome == caught ); + VERIFY( !called ); + } +} diff --git a/libstdc++-v3/testsuite/20_util/optional/observers/4.cc b/libstdc++-v3/testsuite/20_util/optional/observers/4.cc new file mode 100644 index 00000000000..9a305674fb0 --- /dev/null +++ b/libstdc++-v3/testsuite/20_util/optional/observers/4.cc @@ -0,0 +1,35 @@ +// { dg-options "-std=gnu++17" } +// { dg-do run } + +// Copyright (C) 2013-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 +// . + +#include +#include + +struct value_type +{ + int i; +}; + +int main() +{ + std::optional o { value_type { 51 } }; + value_type fallback { 3 }; + VERIFY( o.value_or(fallback).i == 51 ); + VERIFY( o.value_or(fallback).i == (*o).i ); +} diff --git a/libstdc++-v3/testsuite/20_util/optional/observers/5.cc b/libstdc++-v3/testsuite/20_util/optional/observers/5.cc new file mode 100644 index 00000000000..386d81de2e0 --- /dev/null +++ b/libstdc++-v3/testsuite/20_util/optional/observers/5.cc @@ -0,0 +1,40 @@ +// { dg-options "-std=gnu++17" } +// { dg-do run } + +// Copyright (C) 2013-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 +// . + +#include +#include + +struct value_type +{ + int i; +}; + +int main() +{ + { + std::optional o = std::nullopt; + VERIFY( !o ); + } + + { + std::optional o { value_type { 51 } }; + VERIFY( o ); + } +} diff --git a/libstdc++-v3/testsuite/20_util/optional/relops/1.cc b/libstdc++-v3/testsuite/20_util/optional/relops/1.cc new file mode 100644 index 00000000000..62770329eff --- /dev/null +++ b/libstdc++-v3/testsuite/20_util/optional/relops/1.cc @@ -0,0 +1,85 @@ +// { dg-options "-std=gnu++17" } +// { dg-do run } + +// Copyright (C) 2013-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 +// . + +#include +#include + +#include +#include + +namespace ns +{ + struct value_type + { + int i; + std::string s; + }; + + bool + operator==(value_type const& lhs, value_type const& rhs) + { return std::tie(lhs.i, lhs.s) == std::tie(rhs.i, rhs.s); } + + bool + operator<(value_type const& lhs, value_type const& rhs) + { return std::tie(lhs.i, lhs.s) < std::tie(rhs.i, rhs.s); } + +} // namespace ns + +int main() +{ + using ns::value_type; + using O = std::optional; + + { + O o, p; + VERIFY( o == p ); + VERIFY( !(o != p) ); + } + + { + O o { value_type { 42, "forty-two" } }, p; + VERIFY( !(o == p) ); + VERIFY( o != p ); + } + + { + O o, p { value_type { 42, "forty-two" } }; + VERIFY( !(o == p) ); + VERIFY( o != p ); + } + + { + O o { value_type { 11, "eleventy" } }, p { value_type { 42, "forty-two" } }; + VERIFY( !(o == p) ); + VERIFY( o != p ); + } + + { + O o { value_type { 42, "forty-two" } }, p { value_type { 11, "eleventy" } }; + VERIFY( !(o == p) ); + VERIFY( o != p ); + } + + { + O o { value_type { 42, "forty-two" } }, p { value_type { 42, "forty-two" } }; + VERIFY( o == p ); + VERIFY( !(o != p) ); + } +} diff --git a/libstdc++-v3/testsuite/20_util/optional/relops/2.cc b/libstdc++-v3/testsuite/20_util/optional/relops/2.cc new file mode 100644 index 00000000000..65071c04bce --- /dev/null +++ b/libstdc++-v3/testsuite/20_util/optional/relops/2.cc @@ -0,0 +1,97 @@ +// { dg-options "-std=gnu++17" } +// { dg-do run } + +// Copyright (C) 2013-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 +// . + +#include +#include + +#include +#include + +namespace ns +{ + struct value_type + { + int i; + std::string s; + }; + + bool + operator==(value_type const& lhs, value_type const& rhs) + { return std::tie(lhs.i, lhs.s) == std::tie(rhs.i, rhs.s); } + + bool + operator<(value_type const& lhs, value_type const& rhs) + { return std::tie(lhs.i, lhs.s) < std::tie(rhs.i, rhs.s); } + +} // namespace ns + +int main() +{ + using ns::value_type; + using O = std::optional; + + { + O o, p; + VERIFY( !(o < p) ); + VERIFY( !(o > p) ); + VERIFY( o <= p ); + VERIFY( o >= p ); + } + + { + O o { value_type { 42, "forty-two" } }, p; + VERIFY( !(o < p) ); + VERIFY( o > p ); + VERIFY( !(o <= p) ); + VERIFY( o >= p ); + } + + { + O o, p { value_type { 42, "forty-two" } }; + VERIFY( o < p ); + VERIFY( !(o > p) ); + VERIFY( o <= p ); + VERIFY( !(o >= p) ); + } + + { + O o { value_type { 11, "eleventy" } }, p { value_type { 42, "forty-two" } }; + VERIFY( o < p ); + VERIFY( !(o > p) ); + VERIFY( o <= p ); + VERIFY( !(o >= p) ); + } + + { + O o { value_type { 42, "forty-two" } }, p { value_type { 11, "eleventy" } }; + VERIFY( !(o < p) ); + VERIFY( o > p ); + VERIFY( !(o <= p) ); + VERIFY( o >= p ); + } + + { + O o { value_type { 42, "forty-two" } }, p { value_type { 42, "forty-two" } }; + VERIFY( !(o < p) ); + VERIFY( !(o > p) ); + VERIFY( o <= p ); + VERIFY( o >= p ); + } +} diff --git a/libstdc++-v3/testsuite/20_util/optional/relops/3.cc b/libstdc++-v3/testsuite/20_util/optional/relops/3.cc new file mode 100644 index 00000000000..2fd9e8bc1e7 --- /dev/null +++ b/libstdc++-v3/testsuite/20_util/optional/relops/3.cc @@ -0,0 +1,75 @@ +// { dg-options "-std=gnu++17" } +// { dg-do run } + +// Copyright (C) 2013-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 +// . + +#include +#include + +#include +#include + +namespace ns +{ + struct value_type + { + int i; + std::string s; + }; + + bool + operator==(value_type const& lhs, value_type const& rhs) + { return std::tie(lhs.i, lhs.s) == std::tie(rhs.i, rhs.s); } + + bool + operator<(value_type const& lhs, value_type const& rhs) + { return std::tie(lhs.i, lhs.s) < std::tie(rhs.i, rhs.s); } + +} // namespace ns + +int main() +{ + using ns::value_type; + using O = std::optional; + + value_type const reference { 42, "forty-two" }; + + { + O o; + VERIFY( !(o == reference) ); + VERIFY( !(reference == o) ); + VERIFY( o != reference ); + VERIFY( reference != o ); + } + + { + O o { value_type { 11, "eleventy" } }; + VERIFY( !(o == reference) ); + VERIFY( !(reference == o) ); + VERIFY( o != reference ); + VERIFY( reference != o ); + } + + { + O o { value_type { 42, "forty-two" } }; + VERIFY( o == reference ); + VERIFY( reference == o ); + VERIFY( !(o != reference) ); + VERIFY( !(reference != o) ); + } +} diff --git a/libstdc++-v3/testsuite/20_util/optional/relops/4.cc b/libstdc++-v3/testsuite/20_util/optional/relops/4.cc new file mode 100644 index 00000000000..363e633a40c --- /dev/null +++ b/libstdc++-v3/testsuite/20_util/optional/relops/4.cc @@ -0,0 +1,87 @@ +// { dg-options "-std=gnu++17" } +// { dg-do run } + +// Copyright (C) 2013-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 +// . + +#include +#include + +#include +#include + +namespace ns +{ + struct value_type + { + int i; + std::string s; + }; + + bool + operator==(value_type const& lhs, value_type const& rhs) + { return std::tie(lhs.i, lhs.s) == std::tie(rhs.i, rhs.s); } + + bool + operator<(value_type const& lhs, value_type const& rhs) + { return std::tie(lhs.i, lhs.s) < std::tie(rhs.i, rhs.s); } + +} // namespace ns + +int main() +{ + using ns::value_type; + using O = std::optional; + + value_type const reference { 42, "forty-two" }; + + { + O o; + VERIFY( o < reference ); + VERIFY( !(reference < o) ); + VERIFY( !(o > reference) ); + VERIFY( reference > o ); + VERIFY( o <= reference ); + VERIFY( !(reference <= o) ); + VERIFY( !(o >= reference) ); + VERIFY( reference >= o ); + } + + { + O o { value_type { 11, "eleventy" } }; + VERIFY( o < reference ); + VERIFY( !(reference < o) ); + VERIFY( !(o > reference) ); + VERIFY( reference > o ); + VERIFY( o <= reference ); + VERIFY( !(reference <= o) ); + VERIFY( !(o >= reference) ); + VERIFY( reference >= o ); + } + + { + O o { value_type { 42, "forty-two" } }; + VERIFY( !(o < reference) ); + VERIFY( !(reference < o) ); + VERIFY( !(o > reference) ); + VERIFY( !(reference > o) ); + VERIFY( o <= reference ); + VERIFY( reference <= o ); + VERIFY( o >= reference ); + VERIFY( reference >= o ); + } +} diff --git a/libstdc++-v3/testsuite/20_util/optional/relops/5.cc b/libstdc++-v3/testsuite/20_util/optional/relops/5.cc new file mode 100644 index 00000000000..e79e0dbc278 --- /dev/null +++ b/libstdc++-v3/testsuite/20_util/optional/relops/5.cc @@ -0,0 +1,66 @@ +// { dg-options "-std=gnu++17" } +// { dg-do run } + +// Copyright (C) 2013-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 +// . + +#include +#include + +#include +#include + +namespace ns +{ + struct value_type + { + int i; + std::string s; + }; + + bool + operator==(value_type const& lhs, value_type const& rhs) + { return std::tie(lhs.i, lhs.s) == std::tie(rhs.i, rhs.s); } + + bool + operator<(value_type const& lhs, value_type const& rhs) + { return std::tie(lhs.i, lhs.s) < std::tie(rhs.i, rhs.s); } + +} // namespace ns + +int main() +{ + using ns::value_type; + using O = std::optional; + using std::nullopt; + + { + O o; + VERIFY( o == nullopt ); + VERIFY( nullopt == o ); + VERIFY( !(o != nullopt) ); + VERIFY( !(nullopt != o) ); + } + + { + O o { std::in_place }; + VERIFY( !(o == nullopt) ); + VERIFY( !(nullopt == o) ); + VERIFY( o != nullopt ); + VERIFY( nullopt != o ); + } +} diff --git a/libstdc++-v3/testsuite/20_util/optional/relops/6.cc b/libstdc++-v3/testsuite/20_util/optional/relops/6.cc new file mode 100644 index 00000000000..4ead5d1acda --- /dev/null +++ b/libstdc++-v3/testsuite/20_util/optional/relops/6.cc @@ -0,0 +1,74 @@ +// { dg-options "-std=gnu++17" } +// { dg-do run } + +// Copyright (C) 2013-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 +// . + +#include +#include + +#include +#include + +namespace ns +{ + struct value_type + { + int i; + std::string s; + }; + + bool + operator==(value_type const& lhs, value_type const& rhs) + { return std::tie(lhs.i, lhs.s) == std::tie(rhs.i, rhs.s); } + + bool + operator<(value_type const& lhs, value_type const& rhs) + { return std::tie(lhs.i, lhs.s) < std::tie(rhs.i, rhs.s); } + +} // namespace ns + +int main() +{ + using ns::value_type; + using O = std::optional; + using std::nullopt; + + { + O o; + VERIFY( !(o < nullopt) ); + VERIFY( !(nullopt < o) ); + VERIFY( !(o > nullopt) ); + VERIFY( !(nullopt > o) ); + VERIFY( o <= nullopt ); + VERIFY( nullopt <= o ); + VERIFY( o >= nullopt ); + VERIFY( nullopt >= o ); + } + + { + O o { std::in_place }; + VERIFY( !(o < nullopt) ); + VERIFY( nullopt < o ); + VERIFY( o > nullopt ); + VERIFY( !(nullopt > o) ); + VERIFY( !(o <= nullopt) ); + VERIFY( nullopt <= o ); + VERIFY( o >= nullopt ); + VERIFY( !(nullopt >= o) ); + } +} diff --git a/libstdc++-v3/testsuite/20_util/optional/requirements.cc b/libstdc++-v3/testsuite/20_util/optional/requirements.cc new file mode 100644 index 00000000000..aab572f5795 --- /dev/null +++ b/libstdc++-v3/testsuite/20_util/optional/requirements.cc @@ -0,0 +1,259 @@ +// { dg-options "-std=gnu++17" } +// { dg-do run } + +// Copyright (C) 2013-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 +// . + +#include +#include + +#include + +using std::bad_optional_access; +static_assert( std::is_default_constructible::value, "" ); + +struct trivially_destructible +{ + trivially_destructible() = delete; + trivially_destructible(trivially_destructible const&) = delete; + trivially_destructible& operator=(trivially_destructible const&) = delete; + trivially_destructible(trivially_destructible&&) = delete; + trivially_destructible& operator=(trivially_destructible&&) = delete; + ~trivially_destructible() noexcept = default; +}; + +static_assert( std::is_trivially_destructible(), "" ); + +struct no_default_constructor +{ + no_default_constructor() = delete; +}; + +struct no_copy_constructor +{ + no_copy_constructor() = default; + no_copy_constructor(no_copy_constructor const&) = delete; + no_copy_constructor& operator=(no_copy_constructor const&) = default; + no_copy_constructor(no_copy_constructor&&) = default; + no_copy_constructor& operator=(no_copy_constructor&&) = default; +}; + +struct no_copy_assignment +{ + no_copy_assignment() = default; + no_copy_assignment(no_copy_assignment const&) = default; + no_copy_assignment(no_copy_assignment&&) = default; + no_copy_assignment& operator=(no_copy_assignment&&) = default; +}; + +struct no_move_constructor +{ + no_move_constructor() = default; + no_move_constructor(no_move_constructor const&) = default; + no_move_constructor& operator=(no_move_constructor const&) = default; + no_move_constructor(no_move_constructor&&) = delete; + no_move_constructor& operator=(no_move_constructor&&) = default; +}; + +struct no_move_assignment +{ + no_move_assignment() = default; + no_move_assignment(no_move_assignment const&) = default; + no_move_assignment& operator=(no_move_assignment const&) = default; + no_move_assignment(no_move_assignment&&) = default; + no_move_assignment& operator=(no_move_assignment&&) = delete; +}; + +struct no_copy : no_copy_constructor, no_copy_assignment { }; +struct no_move : no_move_constructor, no_move_assignment { }; + +// Laxest possible model of a value type for optional +struct only_destructible +{ + only_destructible(only_destructible&&) = delete; +}; + +int main() +{ + { + static_assert( std::is_trivially_destructible>(), "" ); + } + + { + using T = no_default_constructor; + using O = std::optional; + static_assert( std::is_same(), "" ); + static_assert( std::is_default_constructible(), "" ); + { O o; } + static_assert( std::is_copy_constructible(), "" ); + { O o; auto copy = o; } + static_assert( std::is_copy_assignable(), "" ); + { O o, p; p = o; } + static_assert( std::is_move_constructible(), "" ); + { O o; auto moved_to = std::move(o); } + static_assert( std::is_move_assignable(), "" ); + { O o, p; p = std::move(o); } + } + + { + using T = no_copy_constructor; + using O = std::optional; + static_assert( std::is_same(), "" ); + static_assert( std::is_default_constructible(), "" ); + { O o; } + static_assert( !std::is_copy_constructible(), "" ); + static_assert( !std::is_copy_assignable(), "" ); + static_assert( std::is_move_constructible(), "" ); + { O o; auto moved_to = std::move(o); } + static_assert( std::is_move_assignable(), "" ); + { O o, p; p = std::move(o); } + } + + { + using T = no_copy_assignment; + using O = std::optional; + static_assert( std::is_default_constructible(), "" ); + { O o; } + static_assert( std::is_copy_constructible(), "" ); + { O o; auto copy = o; } + static_assert( !std::is_copy_assignable(), "" ); + static_assert( std::is_move_constructible(), "" ); + { O o; auto moved_to = std::move(o); } + static_assert( std::is_move_assignable(), "" ); + { O o, p; p = std::move(o); } + } + + { + using T = no_copy; + using O = std::optional; + static_assert( std::is_same(), "" ); + static_assert( std::is_default_constructible(), "" ); + { O o; } + static_assert( !std::is_copy_constructible(), "" ); + static_assert( !std::is_copy_assignable(), "" ); + static_assert( std::is_move_constructible(), "" ); + { O o; auto moved_to = std::move(o); } + static_assert( std::is_move_assignable(), "" ); + { O o, p; p = std::move(o); } + } + + { + using T = no_move_constructor; + using O = std::optional; + static_assert( std::is_same(), "" ); + static_assert( std::is_default_constructible(), "" ); + { O o; } + static_assert( std::is_copy_constructible(), "" ); + { O o; auto copy = o; } + static_assert( std::is_copy_assignable(), "" ); + /* + * T should be move constructible due to [12.8/11], which is a new rule in C++1y + * not yet implemented by GCC. Because there is already a special exception in C++11 + * for the generation of the special members that GCC implements (at least some of the + * time), this does not affect the std::optional implementation however. So the assertion + * for T should be changed (or removed altogether) when the time comes, but the rest + * should however remain correct and unchanged. + */ + static_assert( !std::is_move_constructible(), "" ); + static_assert( std::is_move_constructible(), "" ); + { O o; auto moved_to = std::move(o); } + static_assert( std::is_move_assignable(), "" ); + { O o, p; p = std::move(o); } + } + + { + using T = no_move_assignment; + using O = std::optional; + static_assert( std::is_same(), "" ); + static_assert( std::is_default_constructible(), "" ); + { O o; } + static_assert( std::is_copy_constructible(), "" ); + { O o; auto copy = o; } + static_assert( std::is_copy_assignable(), "" ); + { O o, p; p = o; } + static_assert( std::is_move_constructible(), "" ); + { O o; auto moved_to = std::move(o); } + /* + * Paragraph 23 of same leads to a similar situation but with respect to move + * assignment. + */ + static_assert( !std::is_move_assignable(), "" ); + static_assert( std::is_move_assignable(), "" ); + { O o, p; p = std::move(o); } + } + + { + using T = no_move; + using O = std::optional; + static_assert( std::is_same(), "" ); + static_assert( std::is_default_constructible(), "" ); + { O o; } + static_assert( std::is_copy_constructible(), "" ); + { O o; auto copy = o; } + static_assert( std::is_copy_assignable(), "" ); + { O o, p; p = o; } + static_assert( std::is_move_constructible(), "" ); + { O o; auto moved_to = std::move(o); } + static_assert( std::is_move_assignable(), "" ); + { O o, p; p = std::move(o); } + } + + { + using T = only_destructible; + using O = std::optional; + static_assert( std::is_same(), "" ); + static_assert( std::is_default_constructible(), "" ); + { O o; } + static_assert( !std::is_copy_constructible(), "" ); + static_assert( !std::is_copy_assignable(), "" ); + static_assert( !std::is_move_constructible(), "" ); + static_assert( !std::is_move_assignable(), "" ); + } + + { + /* + * Should not complain about 'invalid' specializations as long as + * they're not instantiated. + */ + using A = std::optional; + using B = std::optional; + using C1 = std::optional; + using C2 = std::optional; + using C3 = std::optional; + using C4 = std::optional; + using D1 = std::optional; + using D2 = std::optional; + using D3 = std::optional; + using D4 = std::optional; + + using X = std::tuple; + } + + { + std::optional o { 42 }; + static_assert( std::is_same(), "" ); + VERIFY( o ); + VERIFY( *o == 42 ); + } + + { + constexpr std::optional o { 33 }; + static_assert( std::is_same(), "" ); + static_assert( o, "" ); + static_assert( *o == 33, "" ); + } +} diff --git a/libstdc++-v3/testsuite/20_util/optional/swap/1.cc b/libstdc++-v3/testsuite/20_util/optional/swap/1.cc new file mode 100644 index 00000000000..b077fe4c583 --- /dev/null +++ b/libstdc++-v3/testsuite/20_util/optional/swap/1.cc @@ -0,0 +1,95 @@ +// { dg-options "-std=gnu++17" } +// { dg-do run } + +// Copyright (C) 2013-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 +// . + +#include +#include + +struct exception {}; + +int counter = 0; + +struct mixin_counter +{ + mixin_counter() { ++counter; } + mixin_counter(mixin_counter const&) { ++counter; } + ~mixin_counter() { --counter; } +}; + +namespace ns +{ + +struct value_type : private mixin_counter +{ + explicit value_type(int state) : state(state) { } + int state; +}; + +int swaps = 0; + +void +swap(value_type& lhs, value_type& rhs) +{ + ++swaps; + using std::swap; + swap(lhs.state, rhs.state); +} + +} // namespace ns + +int main() +{ + using O = std::optional; + + VERIFY( ns::swaps == 0 ); + + { + O o, p; + swap(o, p); + VERIFY( !o ); + VERIFY( !p ); + } + + { + O o { std::in_place, 45 }, p; + swap(o, p); + VERIFY( !o ); + VERIFY( p && p->state == 45 ); + } + + { + O o, p { std::in_place, 45 }; + swap(o, p); + VERIFY( o && o->state == 45 ); + VERIFY( !p ); + } + + { + O o { std::in_place, 167 }, p { std::in_place, 999 }; + VERIFY( ns::swaps == 0 ); + + swap(o, p); + + VERIFY( o && o->state == 999 ); + VERIFY( p && p->state == 167 ); + VERIFY( ns::swaps == 1 ); + } + + VERIFY( counter == 0 ); +} diff --git a/libstdc++-v3/testsuite/20_util/optional/typedefs.cc b/libstdc++-v3/testsuite/20_util/optional/typedefs.cc new file mode 100644 index 00000000000..5ec95d850ec --- /dev/null +++ b/libstdc++-v3/testsuite/20_util/optional/typedefs.cc @@ -0,0 +1,33 @@ +// { dg-options "-std=gnu++17" } +// { dg-do compile } + +// Copyright (C) 2014-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 +// . + +#include +#include +#include + +template + using check1_t = std::optional; + +using check2_t = std::in_place_t; +using check3_t = std::nullopt_t; +using check4_t = std::bad_optional_access; + +static_assert(std::is_base_of::value, + "bad_optional_access must derive from logic_error"); -- 2.30.2