diff options
Diffstat (limited to 'gcc-4.9/libstdc++-v3/include/experimental/optional')
-rw-r--r-- | gcc-4.9/libstdc++-v3/include/experimental/optional | 823 |
1 files changed, 823 insertions, 0 deletions
diff --git a/gcc-4.9/libstdc++-v3/include/experimental/optional b/gcc-4.9/libstdc++-v3/include/experimental/optional new file mode 100644 index 0000000..5f2d93f --- /dev/null +++ b/gcc-4.9/libstdc++-v3/include/experimental/optional @@ -0,0 +1,823 @@ +// <optional> -*- C++ -*- + +// Copyright (C) 2013-2014 Free Software Foundation, Inc. +// +// This file is part of the GNU ISO C++ Library. This library is free +// software; you can redistribute it and/or modify it under the +// terms of the GNU General Public License as published by the +// Free Software Foundation; either version 3, or (at your option) +// any later version. + +// This library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// Under Section 7 of GPL version 3, you are granted additional +// permissions described in the GCC Runtime Library Exception, version +// 3.1, as published by the Free Software Foundation. + +// You should have received a copy of the GNU General Public License and +// a copy of the GCC Runtime Library Exception along with this program; +// see the files COPYING3 and COPYING.RUNTIME respectively. If not, see +// <http://www.gnu.org/licenses/>. + +/** @file experimental/optional + * This is a TS C++ Library header. + */ + +#ifndef _GLIBCXX_EXPERIMENTAL_OPTIONAL +#define _GLIBCXX_EXPERIMENTAL_OPTIONAL 1 + +/** + * @defgroup experimental Experimental + * + * Components specified by various Technical Specifications. + */ + +#if __cplusplus <= 201103L +# include <bits/c++14_warning.h> +#else + +#include <utility> +#include <type_traits> +#include <stdexcept> +#include <new> +#include <initializer_list> +#include <bits/functexcept.h> +#include <bits/functional_hash.h> +#include <bits/enable_special_members.h> + +namespace std _GLIBCXX_VISIBILITY(default) +{ +namespace experimental +{ +_GLIBCXX_BEGIN_NAMESPACE_VERSION + + /** + * @defgroup optional Optional values + * @ingroup experimental + * + * Class template for optional values and surrounding facilities, as + * described in n3793 "A proposal to add a utility class to represent + * optional objects (Revision 5)". + * + * @{ + */ + + // All subsequent [X.Y.n] references are against n3793. + + // [X.Y.4] + template<typename _Tp> + class optional; + + // [X.Y.5] + /// Tag type for in-place construction. + struct in_place_t { }; + + /// Tag for in-place construction. + constexpr in_place_t in_place { }; + + // [X.Y.6] + /// Tag type to disengage optional objects. + struct nullopt_t + { + // 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: + // XXX Should not be inline + explicit bad_optional_access(const string& __arg) : logic_error(__arg) { } + + 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<typename _Tp, typename _Sfinae = void> + struct _Has_addressof_impl : std::false_type { }; + + template<typename _Tp> + struct _Has_addressof_impl<_Tp, + decltype( std::declval<const _Tp&>().operator&(), void() )> + : 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<typename _Tp> + struct _Has_addressof : _Has_addressof_impl<_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<typename _Tp, typename enable_if<!_Has_addressof<_Tp>::value, + int>::type...> + constexpr _Tp* __constexpr_addressof(_Tp& __t) + { return &__t; } + + /** + * @brief Fallback overload that defers to __addressof. + */ + template<typename _Tp, typename enable_if<_Has_addressof<_Tp>::value, + int>::type...> + 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<typename _Tp, bool _ShouldProvideDestructor = + !is_trivially_destructible<_Tp>::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 = typename remove_const<_Tp>::type; + + 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<typename... _Args> + constexpr explicit _Optional_base(in_place_t, _Args&&... __args) + : _M_payload(std::forward<_Args>(__args)...), _M_engaged(true) { } + + template<typename _Up, typename... _Args, + typename enable_if<is_constructible<_Tp, + initializer_list<_Up>&, + _Args&&...>::value, + int>::type...> + 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_constructible<_Tp>, + 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. + _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<typename... _Args> + 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<typename _Tp> + class _Optional_base<_Tp, false> + { + private: + using _Stored_type = typename remove_const<_Tp>::type; + + 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<typename... _Args> + constexpr explicit _Optional_base(in_place_t, _Args&&... __args) + : _M_payload(std::forward<_Args>(__args)...), _M_engaged(true) { } + + template<typename _Up, typename... _Args, + typename enable_if<is_constructible<_Tp, + initializer_list<_Up>&, + _Args&&...>::value, + int>::type...> + 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_constructible<_Tp>, + 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<typename... _Args> + 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; + }; + + /** + * @brief Class template for optional values. + */ + template<typename _Tp> + class optional + : private _Optional_base<_Tp>, + private _Enable_copy_move< + // Copy constructor. + is_copy_constructible<_Tp>::value, + // Copy assignment. + __and_<is_copy_constructible<_Tp>, is_copy_assignable<_Tp>>::value, + // Move constructor. + is_move_constructible<_Tp>::value, + // Move assignment. + __and_<is_move_constructible<_Tp>, is_move_assignable<_Tp>>::value, + // Unique tag type. + optional<_Tp>> + { + static_assert(__and_<__not_<is_same<typename remove_cv<_Tp>::type, + nullopt_t>>, + __not_<is_same<typename remove_cv<_Tp>::type, + in_place_t>>, + __not_<is_reference<_Tp>>>(), + "Invalid instantiation of optional<T>"); + + private: + using _Base = _Optional_base<_Tp>; + + public: + using value_type = _Tp; + + // _Optional_base has the responsibility for construction. + using _Base::_Base; + + // [X.Y.4.3] (partly) Assignment. + optional& + operator=(nullopt_t) noexcept + { + this->_M_reset(); + return *this; + } + + template<typename _Up> + typename enable_if< + is_same<_Tp, typename decay<_Up>::type>::value, + optional& + >::type + operator=(_Up&& __u) + { + static_assert(__and_<is_constructible<_Tp, _Up>, + is_assignable<_Tp&, _Up>>(), + "Cannot assign to value type from argument"); + + if (this->_M_is_engaged()) + this->_M_get() = std::forward<_Up>(__u); + else + this->_M_construct(std::forward<_Up>(__u)); + + return *this; + } + + template<typename... _Args> + 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<typename _Up, typename... _Args> + typename enable_if< + is_constructible<_Tp, + initializer_list<_Up>&, + _Args&&...>::value + >::type + 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(); } + + _Tp& + operator*() + { return 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()); + } + + _Tp& + value() + { + if (this->_M_is_engaged()) + return this->_M_get(); + + __throw_bad_optional_access("Attempt to access value of a " + "disengaged optional object"); + } + + template<typename _Up> + constexpr _Tp + value_or(_Up&& __u) const& + { + static_assert(__and_<is_copy_constructible<_Tp>, + is_convertible<_Up&&, _Tp>>(), + "Cannot return value"); + + return this->_M_is_engaged() + ? this->_M_get() + : static_cast<_Tp>(std::forward<_Up>(__u)); + } + + template<typename _Up> + _Tp + value_or(_Up&& __u) && + { + static_assert(__and_<is_move_constructible<_Tp>, + 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<typename _Tp> + constexpr bool + operator==(const optional<_Tp>& __lhs, const optional<_Tp>& __rhs) + { + return static_cast<bool>(__lhs) == static_cast<bool>(__rhs) + && (!__lhs || *__lhs == *__rhs); + } + + template<typename _Tp> + constexpr bool + operator!=(const optional<_Tp>& __lhs, const optional<_Tp>& __rhs) + { return !(__lhs == __rhs); } + + template<typename _Tp> + constexpr bool + operator<(const optional<_Tp>& __lhs, const optional<_Tp>& __rhs) + { + return static_cast<bool>(__rhs) && (!__lhs || *__lhs < *__rhs); + } + + template<typename _Tp> + constexpr bool + operator>(const optional<_Tp>& __lhs, const optional<_Tp>& __rhs) + { return __rhs < __lhs; } + + template<typename _Tp> + constexpr bool + operator<=(const optional<_Tp>& __lhs, const optional<_Tp>& __rhs) + { return !(__rhs < __lhs); } + + template<typename _Tp> + constexpr bool + operator>=(const optional<_Tp>& __lhs, const optional<_Tp>& __rhs) + { return !(__lhs < __rhs); } + + // [X.Y.9] Comparisons with nullopt. + template<typename _Tp> + constexpr bool + operator==(const optional<_Tp>& __lhs, nullopt_t) noexcept + { return !__lhs; } + + template<typename _Tp> + constexpr bool + operator==(nullopt_t, const optional<_Tp>& __rhs) noexcept + { return !__rhs; } + + template<typename _Tp> + constexpr bool + operator!=(const optional<_Tp>& __lhs, nullopt_t) noexcept + { return static_cast<bool>(__lhs); } + + template<typename _Tp> + constexpr bool + operator!=(nullopt_t, const optional<_Tp>& __rhs) noexcept + { return static_cast<bool>(__rhs); } + + template<typename _Tp> + constexpr bool + operator<(const optional<_Tp>& /* __lhs */, nullopt_t) noexcept + { return false; } + + template<typename _Tp> + constexpr bool + operator<(nullopt_t, const optional<_Tp>& __rhs) noexcept + { return static_cast<bool>(__rhs); } + + template<typename _Tp> + constexpr bool + operator>(const optional<_Tp>& __lhs, nullopt_t) noexcept + { return static_cast<bool>(__lhs); } + + template<typename _Tp> + constexpr bool + operator>(nullopt_t, const optional<_Tp>& /* __rhs */) noexcept + { return false; } + + template<typename _Tp> + constexpr bool + operator<=(const optional<_Tp>& __lhs, nullopt_t) noexcept + { return !__lhs; } + + template<typename _Tp> + constexpr bool + operator<=(nullopt_t, const optional<_Tp>& /* __rhs */) noexcept + { return true; } + + template<typename _Tp> + constexpr bool + operator>=(const optional<_Tp>& /* __lhs */, nullopt_t) noexcept + { return true; } + + template<typename _Tp> + constexpr bool + operator>=(nullopt_t, const optional<_Tp>& __rhs) noexcept + { return !__rhs; } + + // [X.Y.10] Comparisons with value type. + template<typename _Tp> + constexpr bool + operator==(const optional<_Tp>& __lhs, const _Tp& __rhs) + { return __lhs && *__lhs == __rhs; } + + template<typename _Tp> + constexpr bool + operator==(const _Tp& __lhs, const optional<_Tp>& __rhs) + { return __rhs && __lhs == *__rhs; } + + template<typename _Tp> + constexpr bool + operator!=(const optional<_Tp>& __lhs, _Tp const& __rhs) + { return !__lhs || *__lhs != __rhs; } + + template<typename _Tp> + constexpr bool + operator!=(const _Tp& __lhs, const optional<_Tp>& __rhs) + { return !__rhs || __lhs != *__rhs; } + + template<typename _Tp> + constexpr bool + operator<(const optional<_Tp>& __lhs, const _Tp& __rhs) + { return !__lhs || *__lhs < __rhs; } + + template<typename _Tp> + constexpr bool + operator<(const _Tp& __lhs, const optional<_Tp>& __rhs) + { return __rhs && __lhs < *__rhs; } + + template<typename _Tp> + constexpr bool + operator>(const optional<_Tp>& __lhs, const _Tp& __rhs) + { return __lhs && __rhs < *__lhs; } + + template<typename _Tp> + constexpr bool + operator>(const _Tp& __lhs, const optional<_Tp>& __rhs) + { return !__rhs || *__rhs < __lhs; } + + template<typename _Tp> + constexpr bool + operator<=(const optional<_Tp>& __lhs, const _Tp& __rhs) + { return !__lhs || !(__rhs < *__lhs); } + + template<typename _Tp> + constexpr bool + operator<=(const _Tp& __lhs, const optional<_Tp>& __rhs) + { return __rhs && !(*__rhs < __lhs); } + + template<typename _Tp> + constexpr bool + operator>=(const optional<_Tp>& __lhs, const _Tp& __rhs) + { return __lhs && !(*__lhs < __rhs); } + + template<typename _Tp> + constexpr bool + operator>=(const _Tp& __lhs, const optional<_Tp>& __rhs) + { return !__rhs || !(__lhs < *__rhs); } + + // [X.Y.11] + template<typename _Tp> + inline void + swap(optional<_Tp>& __lhs, optional<_Tp>& __rhs) + noexcept(noexcept(__lhs.swap(__rhs))) + { __lhs.swap(__rhs); } + + template<typename _Tp> + constexpr optional<typename decay<_Tp>::type> + make_optional(_Tp&& __t) + { return optional<typename decay<_Tp>::type> { std::forward<_Tp>(__t) }; } + + // @} group optional +_GLIBCXX_END_NAMESPACE_VERSION +} + + // [X.Y.12] + template<typename _Tp> + struct hash<experimental::optional<_Tp>> + { + using result_type = size_t; + using argument_type = experimental::optional<_Tp>; + + size_t + operator()(const experimental::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<size_t>(-3333); + return __t ? hash<_Tp> {}(*__t) : __magic_disengaged_hash; + } + }; +} + +#endif // C++14 + +#endif // _GLIBCXX_EXPERIMENTAL_OPTIONAL |