diff options
author | Konstantin Käfer <mail@kkaefer.com> | 2018-08-10 10:22:38 -0400 |
---|---|---|
committer | Konstantin Käfer <mail@kkaefer.com> | 2018-08-14 17:03:46 -0700 |
commit | a3b6fc149895a7f4c29acd6bba70546edec41438 (patch) | |
tree | 328880a17273390bd131af51481b9bcf8059fc21 /vendor | |
parent | c96d9df798b9baba5134f4d22127b9ba044742b4 (diff) | |
download | qtlocation-mapboxgl-a3b6fc149895a7f4c29acd6bba70546edec41438.tar.gz |
[build] vendor std::expected polyfill
Diffstat (limited to 'vendor')
-rw-r--r-- | vendor/expected/LICENSE.txt | 23 | ||||
-rw-r--r-- | vendor/expected/files.txt | 1 | ||||
-rw-r--r-- | vendor/expected/include/expected.hpp | 1708 | ||||
-rw-r--r-- | vendor/expected/version.txt | 1 |
4 files changed, 1733 insertions, 0 deletions
diff --git a/vendor/expected/LICENSE.txt b/vendor/expected/LICENSE.txt new file mode 100644 index 0000000000..36b7cd93cd --- /dev/null +++ b/vendor/expected/LICENSE.txt @@ -0,0 +1,23 @@ +Boost Software License - Version 1.0 - August 17th, 2003 + +Permission is hereby granted, free of charge, to any person or organization +obtaining a copy of the software and accompanying documentation covered by +this license (the "Software") to use, reproduce, display, distribute, +execute, and transmit the Software, and to prepare derivative works of the +Software, and to permit third-parties to whom the Software is furnished to +do so, all subject to the following: + +The copyright notices in the Software and this entire statement, including +the above license grant, this restriction and the following disclaimer, +must be included in all copies of the Software, in whole or in part, and +all derivative works of the Software, unless such copies or derivative +works are solely in the form of machine-executable object code generated by +a source language processor. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT +SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE +FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE, +ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +DEALINGS IN THE SOFTWARE. diff --git a/vendor/expected/files.txt b/vendor/expected/files.txt new file mode 100644 index 0000000000..258044be9a --- /dev/null +++ b/vendor/expected/files.txt @@ -0,0 +1 @@ +include/expected.hpp diff --git a/vendor/expected/include/expected.hpp b/vendor/expected/include/expected.hpp new file mode 100644 index 0000000000..70298d7237 --- /dev/null +++ b/vendor/expected/include/expected.hpp @@ -0,0 +1,1708 @@ +// This version targets C++11 and later. +// +// Copyright (C) 2016-2018 Martin Moene. +// +// Distributed under the Boost Software License, Version 1.0. +// (See accompanying file LICENSE.txt or copy at http://www.boost.org/LICENSE_1_0.txt) +// +// expected lite is based on: +// A proposal to add a utility class to represent expected monad +// by Vicente J. Botet Escriba and Pierre Talbot. http:://wg21.link/p0323 + +#ifndef NONSTD_EXPECTED_LITE_HPP +#define NONSTD_EXPECTED_LITE_HPP + +#include <cassert> +#include <exception> +#include <functional> +#include <initializer_list> +#include <new> +#include <stdexcept> +#include <system_error> +#include <type_traits> +#include <utility> + +#define expected_lite_VERSION "0.1.0" + +// expected-lite configuration +// +// DXXXXR0: -- +// N4015 : -2 (2014-05-26) +// N4109 : -1 (2014-06-29) +// P0323R0: 0 (2016-05-28) +// P0323R1: 1 (2016-10-12) +// -------: +// P0323R2: 2 (2017-06-15) +// P0323R3: 3 (2017-10-15) +// P0323R4: 4 (2017-11-26) +// P0323R5: 5 (2018-02-08) +// +// expected-lite uses 2 and higher + +#ifndef nsel_P0323R +# define nsel_P0323R 5 +#endif + +// Compiler detection (C++20 is speculative): +// Note: MSVC supports C++14 since it supports C++17. + +#ifdef _MSVC_LANG +# define type_MSVC_LANG _MSVC_LANG +#else +# define type_MSVC_LANG 0 +#endif + +#define type_CPP11 (__cplusplus == 201103L ) +#define nsel_CPP11_OR_GREATER (__cplusplus >= 201103L || type_MSVC_LANG >= 201103L ) +#define nsel_CPP14_OR_GREATER (__cplusplus >= 201402L || type_MSVC_LANG >= 201703L ) +#define nsel_CPP17_OR_GREATER (__cplusplus >= 201703L || type_MSVC_LANG >= 201703L ) +#define nsel_CPP20_OR_GREATER (__cplusplus >= 202000L || type_MSVC_LANG >= 202000L ) + +#if nsel_CPP14_OR_GREATER +# define nsel_constexpr14 constexpr +#else +# define nsel_constexpr14 /*constexpr*/ +#endif + +#if nsel_CPP17_OR_GREATER +# define nsel_inline17 inline +#else +# define nsel_inline17 /*inline*/ +#endif + +// Method enabling + +#define nsel_REQUIRES(...) \ + typename std::enable_if<__VA_ARGS__, void*>::type = 0 + +#define nsel_REQUIRES_0(...) \ + template< bool B = (__VA_ARGS__), typename std::enable_if<B, int>::type = 0 > + +#define nsel_REQUIRES_T(...) \ + typename = typename std::enable_if< (__VA_ARGS__), nonstd::expected_detail::enabler >::type + +// Clang, GNUC, MSVC warning suppression macros: + +#if defined(_MSC_VER) && !defined(__clang__) +# define nsel_COMPILER_MSVC_VERSION (_MSC_VER / 10 - 10 * ( 5 + (_MSC_VER < 1900)) ) +#else +# define nsel_COMPILER_MSVC_VERSION 0 +#endif + +#ifdef __clang__ +# pragma clang diagnostic push +#elif defined __GNUC__ +# pragma GCC diagnostic push +#endif // __clang__ + +#if nsel_COMPILER_MSVC_VERSION >= 140 +# pragma warning( push ) +# define nsel_DISABLE_MSVC_WARNINGS(codes) __pragma( warning(disable: codes) ) +#else +# define nsel_DISABLE_MSVC_WARNINGS(codes) +#endif + +#ifdef __clang__ +# define nsel_RESTORE_WARNINGS() _Pragma("clang diagnostic pop") +#elif defined __GNUC__ +# define nsel_RESTORE_WARNINGS() _Pragma("GCC diagnostic pop") +#elif nsel_COMPILER_MSVC_VERSION >= 140 +# define nsel_RESTORE_WARNINGS() __pragma( warning( pop ) ) +#else +# define nsel_RESTORE_WARNINGS() +#endif + +// Suppress the following MSVC (GSL) warnings: +// - C26409: Avoid calling new and delete explicitly, use std::make_unique<T> instead (r.11) + +nsel_DISABLE_MSVC_WARNINGS( 26409 ) + +namespace nonstd { + +namespace std20 { + +// type traits C++20: + +template< typename T > +struct remove_cvref +{ + typedef typename std::remove_cv< typename std::remove_reference<T>::type >::type type; +}; + +} // namespace std20 + +// forward declaration: + +template< typename T, typename E > +class expected; + +namespace expected_detail { + +/// for nsel_REQUIRES_T + +enum class enabler{}; + +/// discriminated union to hold value or 'error'. + +template< typename T, typename E > +union storage_t +{ + friend class expected<T,E>; + +private: + using value_type = T; + using error_type = E; + + // no-op construction + storage_t() {} + ~storage_t() {} + + void construct_value( value_type const & v ) + { + new( &m_value ) value_type( v ); + } + + void construct_value( value_type && v ) + { + new( &m_value ) value_type( std::move( v ) ); + } + + void destruct_value() + { + m_value.~value_type(); + } + + void construct_error( error_type const & e ) + { + new( &m_error ) error_type( e ); + } + + void construct_error( error_type && e ) + { + new( &m_error ) error_type( std::move( e ) ); + } + + void destruct_error() + { + m_error.~error_type(); + } + + constexpr value_type const & value() const & + { + return m_value; + } + + value_type & value() & + { + return m_value; + } + + constexpr value_type const && value() const && + { + return std::move( m_value ); + } + + nsel_constexpr14 value_type && value() && + { + return std::move( m_value ); + } + + value_type const * value_ptr() const + { + return &m_value; + } + + value_type * value_ptr() + { + return &m_value; + } + + error_type const & error() const + { + return m_error; + } + + error_type & error() + { + return m_error; + } + +private: + value_type m_value; + error_type m_error; +}; + +/// discriminated union to hold only 'error'. + +template< typename E > +union storage_t<void, E> +{ + friend class expected<void,E>; + +private: + using value_type = void; + using error_type = E; + + // no-op construction + storage_t() {} + ~storage_t() {} + + void construct_error( error_type const & e ) + { + new( &m_error ) error_type( e ); + } + + void construct_error( error_type && e ) + { + new( &m_error ) error_type( std::move( e ) ); + } + + void destruct_error() + { + m_error.~error_type(); + } + + error_type const & error() const + { + return m_error; + } + + error_type & error() + { + return m_error; + } + +private: + error_type m_error; +}; + +} // namespace expected_detail + +/// // x.x.3 Unexpected object type; unexpected_type; C++17 and later can also use aliased type unexpected. + +#if nsel_P0323R <= 2 +template< typename E = std::exception_ptr > +class unexpected_type +#else +template< typename E > +class unexpected_type +#endif // nsel_P0323R +{ +public: + using error_type = E; + + unexpected_type() = delete; + constexpr unexpected_type( unexpected_type const &) = default; + constexpr unexpected_type( unexpected_type &&) = default; + nsel_constexpr14 unexpected_type& operator=( unexpected_type const &) = default; + nsel_constexpr14 unexpected_type& operator=( unexpected_type &&) = default; + + template< typename E2, nsel_REQUIRES_T( + std::is_constructible<E,E2&&>::value ) + > + constexpr explicit unexpected_type( E2 && error ) + : m_error( std::forward<E2>( error ) ) + {} + + template< typename E2 > + constexpr explicit unexpected_type( unexpected_type<E2> const & error, nsel_REQUIRES( + std::is_constructible<E,E2 const &>::value + && !std::is_convertible<E2 const &, E>::value /*=> explicit */ ) + ) + : m_error( error ) + {} + + template< typename E2 > + constexpr /*non-explicit*/ unexpected_type( unexpected_type<E2> const & error, nsel_REQUIRES( + std::is_constructible<E,E2 const &>::value + && std::is_convertible<E2 const &, E>::value /*=> non-explicit */ ) + ) + : m_error( error ) + {} + + template< typename E2 > + constexpr explicit unexpected_type( unexpected_type<E2> && error, nsel_REQUIRES( + std::is_constructible<E,E2&&>::value + && !std::is_convertible<E2&&, E>::value /*=> explicit */ ) + ) + : m_error( error ) + {} + + template< typename E2 > + constexpr /*non-explicit*/ unexpected_type( unexpected_type<E2> && error, nsel_REQUIRES( + std::is_constructible<E,E2&&>::value + && std::is_convertible<E2&&, E>::value /*=> non-explicit */ ) + ) + : m_error( error ) + {} + + nsel_constexpr14 E & value() & noexcept + { + return m_error; + } + + constexpr E const & value() const & noexcept + { + return m_error; + } + + nsel_constexpr14 E && value() && noexcept + { + return std::move( m_error ); + } + + constexpr E const && value() const && noexcept + { + return std::move( m_error ); + } + +// , nsel_REQUIRES( +// std::is_move_constructible<E>::value +// && std::is_swappable<E>::value ) + + void swap( unexpected_type & rhs ) noexcept ( +#if nsel_CPP17_OR_GREATER + std::is_nothrow_move_constructible<E>::value + && std::is_nothrow_swappable<E&>::value +#else + std::is_nothrow_move_constructible<E>::value + && noexcept ( std::swap( std::declval<E&>(), std::declval<E&>() ) ) +#endif + ) + { + using std::swap; + swap( m_error, rhs.m_error ); + } + +private: + error_type m_error; +}; + +/// class unexpected_type, std::exception_ptr specialization (P0323R2) + +#if nsel_P0323R <= 2 + +template<> +class unexpected_type< std::exception_ptr > +{ +public: + using error_type = std::exception_ptr; + + unexpected_type() = delete; + + ~unexpected_type(){} + + explicit unexpected_type( std::exception_ptr const & error ) + : m_error( error ) + {} + + explicit unexpected_type(std::exception_ptr && error ) + : m_error( std::move( error ) ) + {} + + template< typename E > + explicit unexpected_type( E error ) + : m_error( std::make_exception_ptr( error ) ) + {} + + std::exception_ptr const & value() const + { + return m_error; + } + + std::exception_ptr & value() + { + return m_error; + } + +private: + std::exception_ptr m_error; +}; + +#endif // nsel_P0323R + +/// x.x.4, Unexpected equality operators + +template< typename E > +constexpr bool operator==( unexpected_type<E> const & x, unexpected_type<E> const & y ) +{ + return x.value() == y.value(); +} + +template< typename E > +constexpr bool operator!=( unexpected_type<E> const & x, unexpected_type<E> const & y ) +{ + return ! ( x == y ); +} + +#if nsel_P0323R <= 2 + +template< typename E > +constexpr bool operator<( unexpected_type<E> const & x, unexpected_type<E> const & y ) +{ + return x.value() < y.value(); +} + +template< typename E > +constexpr bool operator>( unexpected_type<E> const & x, unexpected_type<E> const & y ) +{ + return ( y < x ); +} + +template< typename E > +constexpr bool operator<=( unexpected_type<E> const & x, unexpected_type<E> const & y ) +{ + return ! ( y < x ); +} + +template< typename E > +constexpr bool operator>=( unexpected_type<E> const & x, unexpected_type<E> const & y ) +{ + return ! ( x < y ); +} + +/// x.x.5 Specialized algorithms + +template< typename E > +void swap( unexpected_type<E> & x, unexpected_type<E> & y) noexcept ( noexcept ( x.swap(y) ) ) +{ + x.swap( y ); +} + +// unexpected: relational operators for std::exception_ptr: + +inline constexpr bool operator<( unexpected_type<std::exception_ptr> const & /*x*/, unexpected_type<std::exception_ptr> const & /*y*/ ) +{ + return false; +} + +inline constexpr bool operator>( unexpected_type<std::exception_ptr> const & /*x*/, unexpected_type<std::exception_ptr> const & /*y*/ ) +{ + return false; +} + +inline constexpr bool operator<=( unexpected_type<std::exception_ptr> const & x, unexpected_type<std::exception_ptr> const & y ) +{ + return ( x == y ); +} + +inline constexpr bool operator>=( unexpected_type<std::exception_ptr> const & x, unexpected_type<std::exception_ptr> const & y ) +{ + return ( x == y ); +} + +#endif // nsel_P0323R + +// unexpected: traits + +#if nsel_P0323R <= 3 + +template <typename E> +struct is_unexpected : std::false_type {}; + +template <typename E> +struct is_unexpected< unexpected_type<E> > : std::true_type {}; + +#endif // nsel_P0323R + +// unexpected: factory + +// keep make_unexpected() removed in p0323r2 for pre-C++17: + +template< typename E> +nsel_constexpr14 auto +make_unexpected( E && v) -> unexpected_type< typename std::decay<E>::type > +{ + return unexpected_type< typename std::decay<E>::type >( v ); +} + +#if nsel_P0323R <= 3 + +/*nsel_constexpr14*/ auto inline +make_unexpected_from_current_exception() -> unexpected_type< std::exception_ptr > +{ + return unexpected_type< std::exception_ptr >( std::current_exception() ); +} + +#endif // nsel_P0323R + +/// in-place tag: construct a value in-place (should come from std::experimental::optional) + +struct in_place_t{}; + +nsel_inline17 constexpr in_place_t in_place{}; + +/// unexpect tag, in_place_unexpected tag: construct an error + +struct unexpect_t{}; +using in_place_unexpected_t = unexpect_t; + +nsel_inline17 constexpr unexpect_t unexpect{}; +nsel_inline17 constexpr unexpect_t in_place_unexpected{}; + +/// expected access error + +template< typename E > +class bad_expected_access; + +template <> +class bad_expected_access< void > : public std::exception +{ +public: + explicit bad_expected_access() + : std::exception() + {} +}; + +template< typename E > +class bad_expected_access : public bad_expected_access< void > +{ +public: + using error_type = E; + + explicit bad_expected_access( error_type error ) + : m_error( error ) + {} + + virtual char const * what() const noexcept override + { + return "bad_expected_access"; + } + + nsel_constexpr14 error_type & error() & + { + return m_error; + } + + constexpr error_type const & error() const & + { + return m_error; + } + + nsel_constexpr14 error_type && error() && + { + return std::move( m_error ); + } + + constexpr error_type const && error() const && + { + return std::move( m_error ); + } + +private: + error_type m_error; +}; + +/// class error_traits + +template< typename Error > +struct error_traits +{ + static void rethrow( Error const & e ) + { + throw bad_expected_access<Error>{ e }; + } +}; + +template<> +struct error_traits< std::exception_ptr > +{ + static void rethrow( std::exception_ptr const & e ) + { + std::rethrow_exception( e ); + } +}; + +template<> +struct error_traits< std::error_code > +{ + static void rethrow( std::error_code const & e ) + { + throw std::system_error( e ); + } +}; + +/// class expected + +#if nsel_P0323R <= 2 +template< typename T, typename E = std::exception_ptr > +class expected +#else +template< typename T, typename E > +class expected +#endif // nsel_P0323R +{ +public: + using value_type = T; + using error_type = E; + using unexpected_type = nonstd::unexpected_type<E>; + + template< typename U > + struct rebind + { + using type = expected<U, error_type>; + }; + + // x.x.4.1 constructors + + nsel_REQUIRES_0( + std::is_default_constructible<T>::value + ) + nsel_constexpr14 expected() noexcept + ( + std::is_nothrow_default_constructible<T>::value + ) + : has_value_( true ) + { + contained.construct_value( value_type() ); + } + + nsel_constexpr14 expected( expected const & rhs +// , nsel_REQUIRES( +// std::is_copy_constructible<T>::value +// && std::is_copy_constructible<E>::value ) + ) + : has_value_( rhs.has_value_ ) + { + if ( has_value() ) contained.construct_value( rhs.contained.value() ); + else contained.construct_error( rhs.contained.error() ); + } + + nsel_constexpr14 expected( expected && rhs +// , nsel_REQUIRES( +// std::is_move_constructible<T>::value +// && std::is_move_constructible<E>::value ) + ) noexcept ( + std::is_nothrow_move_constructible<T>::value + && std::is_nothrow_move_constructible<E>::value + ) + : has_value_( rhs.has_value_ ) + { + if ( has_value() ) contained.construct_value( std::move( rhs.contained.value() ) ); + else contained.construct_error( std::move( rhs.contained.error() ) ); + } + + template< typename U, typename G > + nsel_constexpr14 explicit expected( expected<U, G> const & rhs, nsel_REQUIRES( + std::is_constructible<T, const U&>::value + && std::is_constructible<E, const G&>::value + && !std::is_constructible<T, expected<U, G>&>::value + && !std::is_constructible<T, expected<U, G>&&>::value + && !std::is_constructible<T, const expected<U, G>&>::value + && !std::is_constructible<T, const expected<U, G>&&>::value + && !std::is_convertible<expected<U, G>&, T>::value + && !std::is_convertible<expected<U, G>&&, T>::value + && !std::is_convertible<const expected<U, G>&, T>::value + && !std::is_convertible<const expected<U, G>&&, T>::value + && (!std::is_convertible<U const&, T>::value || !std::is_convertible<const G&, E>::value ) /*=> explicit */ ) + ) + : has_value_( rhs.has_value_ ) + { + if ( has_value() ) contained.construct_value( rhs.contained.value() ); + else contained.construct_error( rhs.contained.error() ); + } + + template< typename U, typename G > + nsel_constexpr14 /*non-explicit*/ expected( expected<U, G> const & rhs, nsel_REQUIRES( + std::is_constructible<T, const U&>::value + && std::is_constructible<E, const G&>::value + && !std::is_constructible<T, expected<U, G>&>::value + && !std::is_constructible<T, expected<U, G>&&>::value + && !std::is_constructible<T, const expected<U, G>&>::value + && !std::is_constructible<T, const expected<U, G>&&>::value + && !std::is_convertible<expected<U, G>&, T>::value + && !std::is_convertible<expected<U, G>&&, T>::value + && !std::is_convertible<const expected<U, G>&, T>::value + && !std::is_convertible<const expected<U, G>&&, T>::value + && !(!std::is_convertible<U const&, T>::value || !std::is_convertible<const G&, E>::value ) /*=> explicit */ ) + ) + : has_value_( rhs.has_value_ ) + { + if ( has_value() ) contained.construct_value( rhs.contained.value() ); + else contained.construct_error( rhs.contained.error() ); + } + + template< typename U, typename G > + nsel_constexpr14 explicit expected( expected<U, G> && rhs, nsel_REQUIRES( + std::is_constructible<T, U>::value + && std::is_constructible<E, G>::value + && !std::is_constructible<T, expected<U, G>&>::value + && !std::is_constructible<T, expected<U, G>&&>::value + && !std::is_constructible<T, const expected<U, G>&>::value + && !std::is_constructible<T, const expected<U, G>&&>::value + && !std::is_convertible<expected<U, G>&, T>::value + && !std::is_convertible<expected<U, G>&&, T>::value + && !std::is_convertible<const expected<U, G>&, T>::value + && !std::is_convertible<const expected<U, G>&&, T>::value + && (!std::is_convertible<U, T>::value || !std::is_convertible<G, E>::value ) /*=> explicit */ ) + ) + : has_value_( rhs.has_value_ ) + { + if ( has_value() ) contained.construct_value( std::move( rhs.contained.value() ) ); + else contained.construct_error( std::move( rhs.contained.error() ) ); + } + + template< typename U, typename G > + nsel_constexpr14 /*non-explicit*/ expected( expected<U, G> && rhs, nsel_REQUIRES( + std::is_constructible<T, U>::value + && std::is_constructible<E, G>::value + && !std::is_constructible<T, expected<U, G>&>::value + && !std::is_constructible<T, expected<U, G>&&>::value + && !std::is_constructible<T, const expected<U, G>&>::value + && !std::is_constructible<T, const expected<U, G>&&>::value + && !std::is_convertible<expected<U, G>&, T>::value + && !std::is_convertible<expected<U, G>&&, T>::value + && !std::is_convertible<const expected<U, G>&, T>::value + && !std::is_convertible<const expected<U, G>&&, T>::value + && !(!std::is_convertible<U, T>::value || !std::is_convertible<G, E>::value ) /*=> non-explicit */ ) + ) + : has_value_( rhs.has_value_ ) + { + if ( has_value() ) contained.construct_value( std::move( rhs.contained.value() ) ); + else contained.construct_error( std::move( rhs.contained.error() ) ); + } + + nsel_constexpr14 expected( value_type const & v +// , nsel_REQUIRES( +// std::is_copy_constructible<T>::value ) + ) + : has_value_( true ) + { + contained.construct_value( v ); + } + + template< typename U = T > + nsel_constexpr14 explicit expected( U && v, nsel_REQUIRES( + std::is_constructible<T,U&&>::value + && !std::is_same<typename std20::remove_cvref<U>::type, in_place_t>::value + && !std::is_same<expected<T,E>, typename std20::remove_cvref<U>::type>::value + && !std::is_same<nonstd::unexpected_type<E>, typename std20::remove_cvref<U>::type>::value + && !std::is_convertible<U&&,T>::value /*=> explicit */ +) + ) noexcept + ( + std::is_nothrow_move_constructible<U>::value && + std::is_nothrow_move_constructible<E>::value + ) + : has_value_( true ) + { + contained.construct_value( std::forward<U>( v ) ); + } + + template< typename U = T > + nsel_constexpr14 expected( U && v, nsel_REQUIRES( + std::is_constructible<T,U&&>::value + && !std::is_same<typename std20::remove_cvref<U>::type, in_place_t>::value + && !std::is_same<expected<T,E>, typename std20::remove_cvref<U>::type>::value + && !std::is_same<nonstd::unexpected_type<E>, typename std20::remove_cvref<U>::type>::value + && std::is_convertible<U&&,T>::value /*=> non-explicit */ +) + ) noexcept + ( + std::is_nothrow_move_constructible<U>::value && + std::is_nothrow_move_constructible<E>::value + ) + : has_value_( true ) + { + contained.construct_value( std::forward<U>( v ) ); + } + + template <typename... Args, nsel_REQUIRES_T( + std::is_constructible<T, Args&&...>::value ) > + + nsel_constexpr14 explicit expected( in_place_t, Args&&... args ) + : has_value_( true ) + { + contained.construct_value( std::forward<Args>( args )... ); + } + + template< typename U, typename... Args, nsel_REQUIRES_T( + std::is_constructible<T, std::initializer_list<U>, Args&&...>::value ) > + + nsel_constexpr14 explicit expected( in_place_t, std::initializer_list<U> il, Args&&... args ) + : has_value_( true ) + { + contained.construct_value( il, std::forward<Args>( args )... ); + } + + template< typename G = E > + nsel_constexpr14 explicit expected( nonstd::unexpected_type<G> const & error, nsel_REQUIRES( + !std::is_convertible<const G&, E>::value /*=> explicit */ ) + ) + : has_value_( false ) + { + contained.construct_error( error.value() ); + } + + template< typename G = E > + nsel_constexpr14 /*non-explicit*/ expected( nonstd::unexpected_type<G> const & error, nsel_REQUIRES( + std::is_convertible<const G&, E>::value /*=> non-explicit */ ) + ) + : has_value_( false ) + { + contained.construct_error( error.value() ); + } + + template< typename G = E > + nsel_constexpr14 explicit expected( nonstd::unexpected_type<G> && error, nsel_REQUIRES( + !std::is_convertible<G&&, E>::value /*=> explicit */ ) + ) + : has_value_( false ) + { + contained.construct_error( std::move( error.value() ) ); + } + + template< typename G = E > + nsel_constexpr14 /*non-explicit*/ expected( nonstd::unexpected_type<G> && error, nsel_REQUIRES( + std::is_convertible<G&&, E>::value /*=> non-explicit */ ) + ) + : has_value_( false ) + { + contained.construct_error( std::move( error.value() ) ); + } + + template< typename... Args, nsel_REQUIRES_T( + std::is_constructible<E, Args&&...>::value ) + > + nsel_constexpr14 explicit expected( unexpect_t, Args&&... args ) + : has_value_( false ) + { + contained.construct_error( std::forward<Args>( args )... ); + } + + template< typename U, typename... Args, nsel_REQUIRES_T( + std::is_constructible<T, std::initializer_list<U>, Args&&...>::value ) + > + nsel_constexpr14 explicit expected( unexpect_t, std::initializer_list<U> il, Args&&... args ) + : has_value_( false ) + { + contained.construct_error( il, std::forward<Args>( args )... ); + } + + // x.x.4.2 destructor + + ~expected() + { + if ( has_value() ) contained.destruct_value(); + else contained.destruct_error(); + } + + // x.x.4.3 assignment + +// nsel_REQUIRES( +// std::is_copy_constructible<T>::value && +// std::is_copy_assignable<T>::value && +// std::is_copy_constructible<E>::value && +// std::is_copy_assignable<E>::value ) + + expected operator=( expected const & rhs ) + { + expected( rhs ).swap( *this ); + return *this; + } + +// nsel_REQUIRES( +// std::is_move_constructible<T>::value && +// std::is_move_assignable<T>::value && +// std::is_move_constructible<E>::value && +// std::is_move_assignable<E>::value ) + + expected & operator=( expected && rhs ) noexcept + ( + std::is_nothrow_move_assignable<T>::value && + std::is_nothrow_move_constructible<T>::value&& + std::is_nothrow_move_assignable<E>::value && + std::is_nothrow_move_constructible<E>::value ) + { + expected( std::move( rhs ) ).swap( *this ); + return *this; + } + + template< typename U, nsel_REQUIRES_T( + std::is_constructible<T,U>::value && + std::is_assignable<T&, U>::value ) > + + expected & operator=( U && v ) + { + expected( std::forward<U>( v ) ).swap( *this ); + return *this; + } + +// nsel_REQUIRES( +// std::is_copy_constructible<E>::value && +// std::is_assignable<E&, E>::value ) + + expected & operator=( unexpected_type const & u ) + { + expected( std::move( u ) ).swap( *this ); + return *this; + } + +// nsel_REQUIRES( +// std::is_copy_constructible<E>::value && +// std::is_assignable<E&, E>::value ) + + expected & operator=( unexpected_type && u ) + { + expected( std::move( u ) ).swap( *this ); + return *this; + } + + template< typename... Args, nsel_REQUIRES_T( + std::is_constructible<T, Args&&...>::value ) > + + void emplace( Args &&... args ) + { + expected( in_place, std::forward<Args>(args)... ).swap( *this ); + } + + template< typename U, typename... Args, nsel_REQUIRES_T( + std::is_constructible<T, std::initializer_list<U>&, Args&&...>::value ) > + + void emplace( std::initializer_list<U> il, Args &&... args ) + { + expected( in_place, il, std::forward<Args>(args)... ).swap( *this ); + } + + // x.x.4.4 swap + +// nsel_REQUIRES( +// std::is_move_constructible<T>::value && +// std::is_move_constructible<E>::value ) + + void swap( expected & rhs ) noexcept + ( +#if nsel_CPP17_OR_GREATER + std::is_nothrow_move_constructible<T>::value && std::is_nothrow_swappable<T&>::value && + std::is_nothrow_move_constructible<E>::value && std::is_nothrow_swappable<E&>::value +#else + std::is_nothrow_move_constructible<T>::value && noexcept ( std::swap( std::declval<T&>(), std::declval<T&>() ) ) && + std::is_nothrow_move_constructible<E>::value && noexcept ( std::swap( std::declval<E&>(), std::declval<E&>() ) ) +#endif + ) + { + using std::swap; + + if ( bool(*this) && bool(rhs) ) { swap( contained.value(), rhs.contained.value() ); } + else if ( ! bool(*this) && ! bool(rhs) ) { swap( contained.error(), rhs.contained.error() ); } + else if ( bool(*this) && ! bool(rhs) ) { error_type t( std::move( rhs.error() ) ); + rhs.contained.destruct_error(); + rhs.contained.construct_value( std::move( contained.value() ) ); + contained.destruct_value(); + contained.construct_error( std::move( t ) ); + swap( has_value_, rhs.has_value_ ); } + else if ( ! bool(*this) && bool(rhs) ) { rhs.swap( *this ); } + } + + // x.x.4.5 observers + + constexpr value_type const * operator ->() const + { + return assert( has_value() ), contained.value_ptr(); + } + + value_type * operator ->() + { + return assert( has_value() ), contained.value_ptr(); + } + + constexpr value_type const & operator *() const & + { + return assert( has_value() ), contained.value(); + } + + value_type & operator *() & + { + return assert( has_value() ), contained.value(); + } + + constexpr value_type const && operator *() const && + { + return assert( has_value() ), std::move( contained.value() ); + } + + nsel_constexpr14 value_type && operator *() && + { + return assert( has_value() ), std::move( contained.value() ); + } + + constexpr explicit operator bool() const noexcept + { + return has_value(); + } + + constexpr bool has_value() const noexcept + { + return has_value_; + } + + constexpr value_type const & value() const & + { + return has_value() + ? ( contained.value() ) + : ( error_traits<error_type>::rethrow( contained.error() ), contained.value() ); + } + + value_type & value() & + { + return has_value() + ? ( contained.value() ) + : ( error_traits<error_type>::rethrow( contained.error() ), contained.value() ); + } + + constexpr value_type const && value() const && + { + return std::move( has_value() + ? ( contained.value() ) + : ( error_traits<error_type>::rethrow( contained.error() ), contained.value() ) ); + } + + nsel_constexpr14 value_type && value() && + { + return std::move( has_value() + ? ( contained.value() ) + : ( error_traits<error_type>::rethrow( contained.error() ), contained.value() ) ); + } + + constexpr error_type const & error() const & + { + return assert( ! has_value() ), contained.error(); + } + + error_type & error() & + { + return assert( ! has_value() ), contained.error(); + } + + constexpr error_type const && error() const && + { + return assert( ! has_value() ), std::move( contained.error() ); + } + + error_type && error() && + { + return assert( ! has_value() ), std::move( contained.error() ); + } + + constexpr unexpected_type get_unexpected() const + { + return make_unexpected( contained.error() ); + } + + template< typename Ex > + bool has_exception() const + { + using ContainedEx = typename std::remove_reference< decltype( get_unexpected().value() ) >::type; + return ! has_value() && std::is_base_of< Ex, ContainedEx>::value; + } + + template< typename U, nsel_REQUIRES_T( + std::is_copy_constructible<T>::value && + std::is_convertible<U&&, T>::value ) > + + value_type value_or( U && v ) const & + { + return has_value() + ? contained.value() + : static_cast<T>( std::forward<U>( v ) ); + } + + template< typename U, nsel_REQUIRES_T( + std::is_move_constructible<T>::value && + std::is_convertible<U&&, T>::value ) > + + value_type value_or( U && v ) && + { + return has_value() + ? std::move( contained.value() ) + : static_cast<T>( std::forward<U>( v ) ); + } + + // unwrap() + +// template <class U, class E> +// constexpr expected<U,E> expected<expected<U,E>,E>::unwrap() const&; + +// template <class T, class E> +// constexpr expected<T,E> expected<T,E>::unwrap() const&; + +// template <class U, class E> +// expected<U,E> expected<expected<U,E>, E>::unwrap() &&; + +// template <class T, class E> +// template expected<T,E> expected<T,E>::unwrap() &&; + + // factories + +// template <typename Ex, typename F> +// expected<T,E> catch_exception(F&& f); + +// template <typename F> +// expected<decltype(func(declval<T>())),E> map(F&& func) ; + +// template <typename F> +// 'see below' bind(F&& func); + +// template <typename F> +// expected<T,E> catch_error(F&& f); + +// template <typename F> +// 'see below' then(F&& func); + +private: + bool has_value_; + expected_detail::storage_t<T,E> contained; +}; + +/// class expected, void specialization + +template< typename E > +class expected<void, E> +{ +public: + using value_type = void; + using error_type = E; + using unexpected_type = nonstd::unexpected_type<E>; + + // x.x.4.1 constructors + + constexpr expected() noexcept + : has_value_( true ) + { + } + + nsel_constexpr14 expected( expected const & rhs ) + : has_value_( rhs.has_value_ ) + { + if ( ! has_value() ) contained.construct_error( rhs.contained.error() ); + } + + nsel_REQUIRES_0( + std::is_move_constructible<E>::value ) + + nsel_constexpr14 expected( expected && rhs ) noexcept + ( + true // TBD - see also non-void specialization + ) + : has_value_( rhs.has_value_ ) + { + if ( ! has_value() ) contained.construct_error( std::move( rhs.contained.error() ) ); + } + + constexpr explicit expected( in_place_t ) + : has_value_( true ) + { + } + + template< typename G = E > + nsel_constexpr14 explicit expected( nonstd::unexpected_type<G> const & error, nsel_REQUIRES( + !std::is_convertible<const G&, E>::value /*=> explicit */ ) + ) + : has_value_( false ) + { + contained.construct_error( error.value() ); + } + + template< typename G = E > + nsel_constexpr14 /*non-explicit*/ expected( nonstd::unexpected_type<G> const & error, nsel_REQUIRES( + std::is_convertible<const G&, E>::value /*=> non-explicit */ ) + ) + : has_value_( false ) + { + contained.construct_error( error.value() ); + } + + template< typename G = E > + nsel_constexpr14 explicit expected( nonstd::unexpected_type<G> && error, nsel_REQUIRES( + !std::is_convertible<G&&, E>::value /*=> explicit */ ) + ) + : has_value_( false ) + { + contained.construct_error( std::move( error.value() ) ); + } + + template< typename G = E > + nsel_constexpr14 /*non-explicit*/ expected( nonstd::unexpected_type<G> && error, nsel_REQUIRES( + std::is_convertible<G&&, E>::value /*=> non-explicit */ ) + ) + : has_value_( false ) + { + contained.construct_error( std::move( error.value() ) ); + } + + template< typename... Args, nsel_REQUIRES_T( + std::is_constructible<E, Args&&...>::value ) + > + nsel_constexpr14 explicit expected( unexpect_t, Args&&... args ) + : has_value_( false ) + { + contained.construct_error( std::forward<Args>( args )... ); + } + + template< typename U, typename... Args, nsel_REQUIRES_T( + std::is_constructible<U, std::initializer_list<U>, Args&&...>::value ) + > + nsel_constexpr14 explicit expected( unexpect_t, std::initializer_list<U> il, Args&&... args ) + : has_value_( false ) + { + contained.construct_error( il, std::forward<Args>( args )... ); + } + + + // destructor + + ~expected() + { + if ( ! has_value() ) contained.destruct_error(); + } + + // x.x.4.3 assignment + +// nsel_REQUIRES( +// std::is_copy_constructible<E>::value && +// std::is_copy_assignable<E>::value ) + + expected & operator=( expected const & rhs ) + { + expected( rhs ).swap( *this ); + return *this; + } + +// nsel_REQUIRES( +// std::is_move_constructible<E>::value && +// std::is_move_assignable<E>::value ) + + expected & operator=( expected && rhs ) noexcept + ( + std::is_nothrow_move_assignable<E>::value && + std::is_nothrow_move_constructible<E>::value ) + { + expected( std::move( rhs ) ).swap( *this ); + return *this; + } + + void emplace() + {} + + // x.x.4.4 swap + +// nsel_REQUIRES( +// std::is_move_constructible<E>::value ) + + void swap( expected & rhs ) noexcept + ( +#if nsel_CPP17_OR_GREATER + std::is_nothrow_move_constructible<E>::value && std::is_nothrow_swappable<E&>::value +#else + std::is_nothrow_move_constructible<E>::value && noexcept ( std::swap( std::declval<E&>(), std::declval<E&>() ) ) +#endif + ) + { + using std::swap; + + if ( ! bool(*this) && ! bool(rhs) ) { swap( contained.error(), rhs.contained.error() ); } + else if ( bool(*this) && ! bool(rhs) ) { contained.construct_error( std::move( rhs.error() ) ); + swap( has_value_, rhs.has_value_ ); } + else if ( ! bool(*this) && bool(rhs) ) { rhs.swap( *this ); } + } + + // x.x.4.5 observers + + constexpr explicit operator bool() const noexcept + { + return has_value(); + } + + constexpr bool has_value() const noexcept + { + return has_value_; + } + + void value() const + {} + + constexpr error_type const & error() const & + { + return assert( ! has_value() ), contained.error(); + } + + error_type & error() & + { + return assert( ! has_value() ), contained.error(); + } + + constexpr error_type const && error() const && + { + return assert( ! has_value() ), std::move( contained.error() ); + } + + error_type && error() && + { + return assert( ! has_value() ), std::move( contained.error() ); + } + + constexpr unexpected_type get_unexpected() const + { + return make_unexpected( contained.error() ); + } + + template <typename Ex> + bool has_exception() const + { + return ! has_value() && std::is_base_of< Ex, decltype( get_unexpected().value() ) >::value; + } + +// template constexpr 'see below' unwrap() const&; +// +// template 'see below' unwrap() &&; + + // factories + +// template <typename Ex, typename F> +// expected<void,E> catch_exception(F&& f); +// +// template <typename F> +// expected<decltype(func()), E> map(F&& func) ; +// +// template <typename F> +// 'see below' bind(F&& func) ; +// +// template <typename F> +// expected<void,E> catch_error(F&& f); +// +// template <typename F> +// 'see below' then(F&& func); + +private: + bool has_value_; + expected_detail::storage_t<void,E> contained; +}; + +// expected: relational operators + +template <typename T, typename E> +constexpr bool operator==( expected<T,E> const & x, expected<T,E> const & y ) +{ + return bool(x) != bool(y) ? false : bool(x) == false ? true : *x == *y; +} + +template <typename T, typename E> +constexpr bool operator!=( expected<T,E> const & x, expected<T,E> const & y ) +{ + return !(x == y); +} + +template <typename T, typename E> +constexpr bool operator<( expected<T,E> const & x, expected<T,E> const & y ) +{ + return (!y) ? false : (!x) ? true : *x < *y; +} + +template <typename T, typename E> +constexpr bool operator>( expected<T,E> const & x, expected<T,E> const & y ) +{ + return (y < x); +} + +template <typename T, typename E> +constexpr bool operator<=( expected<T,E> const & x, expected<T,E> const & y ) +{ + return !(y < x); +} + +template <typename T, typename E> +constexpr bool operator>=( expected<T,E> const & x, expected<T,E> const & y ) +{ + return !(x < y); +} + +// expected: comparison with unexpected_type + +template <typename T, typename E> +constexpr bool operator==( expected<T,E> const & x, unexpected_type<E> const & u ) +{ + return (!x) ? x.get_unexpected() == u : false; +} + +template <typename T, typename E> +constexpr bool operator==( unexpected_type<E> const & u, expected<T,E> const & x ) +{ + return ( x == u ); +} + +template <typename T, typename E> +constexpr bool operator!=( expected<T,E> const & x, unexpected_type<E> const & u ) +{ + return ! ( x == u ); +} + +template <typename T, typename E> +constexpr bool operator!=( unexpected_type<E> const & u, expected<T,E> const & x ) +{ + return ! ( x == u ); +} + +template <typename T, typename E> +constexpr bool operator<( expected<T,E> const & x, unexpected_type<E> const & u ) +{ + return (!x) ? ( x.get_unexpected() < u ) : false; +} + +#if nsel_P0323R <= 2 + +template <typename T, typename E> +constexpr bool operator<( unexpected_type<E> const & u, expected<T,E> const & x ) +{ + return (!x) ? ( u < x.get_unexpected() ) : true ; +} + +template <typename T, typename E> +constexpr bool operator>( expected<T,E> const & x, unexpected_type<E> const & u ) +{ + return ( u < x ); +} + +template <typename T, typename E> +constexpr bool operator>( unexpected_type<E> const & u, expected<T,E> const & x ) +{ + return ( x < u ); +} + +template <typename T, typename E> +constexpr bool operator<=( expected<T,E> const & x, unexpected_type<E> const & u ) +{ + return ! ( u < x ); +} + +template <typename T, typename E> +constexpr bool operator<=( unexpected_type<E> const & u, expected<T,E> const & x) +{ + return ! ( x < u ); +} + +template <typename T, typename E> +constexpr bool operator>=( expected<T,E> const & x, unexpected_type<E> const & u ) +{ + return ! ( u > x ); +} + +template <typename T, typename E> +constexpr bool operator>=( unexpected_type<E> const & u, expected<T,E> const & x ) +{ + return ! ( x > u ); +} + +#endif // nsel_P0323R + +// expected: comparison with T + +template <typename T, typename E> +constexpr bool operator==( expected<T,E> const & x, T const & v ) +{ + return bool(x) ? *x == v : false; +} + +template <typename T, typename E> +constexpr bool operator==(T const & v, expected<T,E> const & x ) +{ + return bool(x) ? v == *x : false; +} + +template <typename T, typename E> +constexpr bool operator!=( expected<T,E> const & x, T const & v ) +{ + return bool(x) ? *x != v : true; +} + +template <typename T, typename E> +constexpr bool operator!=( T const & v, expected<T,E> const & x ) +{ + return bool(x) ? v != *x : true; +} + +template <typename T, typename E> +constexpr bool operator<( expected<T,E> const & x, T const & v ) +{ + return bool(x) ? *x < v : true; +} + +template <typename T, typename E> +constexpr bool operator<( T const & v, expected<T,E> const & x ) +{ + return bool(x) ? v < *x : false; +} + +template <typename T, typename E> +constexpr bool operator>( T const & v, expected<T,E> const & x ) +{ + return bool(x) ? *x < v : false; +} + +template <typename T, typename E> +constexpr bool operator>( expected<T,E> const & x, T const & v ) +{ + return bool(x) ? v < *x : false; +} + +template <typename T, typename E> +constexpr bool operator<=( T const & v, expected<T,E> const & x ) +{ + return bool(x) ? ! ( *x < v ) : false; +} + +template <typename T, typename E> +constexpr bool operator<=( expected<T,E> const & x, T const & v ) +{ + return bool(x) ? ! ( v < *x ) : true; +} + +template <typename T, typename E> +constexpr bool operator>=( expected<T,E> const & x, T const & v ) +{ + return bool(x) ? ! ( *x < v ) : false; +} + +template <typename T, typename E> +constexpr bool operator>=( T const & v, expected<T,E> const & x ) +{ + return bool(x) ? ! ( v < *x ) : true; +} + +/// x.x.x Specialized algorithms + +template< typename T, typename E > +void swap( expected<T,E> & x, expected<T,E> & y ) noexcept ( noexcept ( x.swap(y) ) ) +{ + x.swap( y ); +} + +#if nsel_P0323R <= 3 + +template< typename T> +constexpr auto make_expected( T && v ) -> expected< typename std::decay<T>::type > +{ + return expected< typename std::decay<T>::type >( std::forward<T>( v ) ); +} + +// expected<void> specialization: + +auto inline make_expected() -> expected<void> +{ + return expected<void>( in_place ); +} + +template< typename T> +constexpr auto make_expected_from_current_exception() -> expected<T> +{ + return expected<T>( make_unexpected_from_current_exception() ); +} + +template< typename T> +auto make_expected_from_exception( std::exception_ptr v ) -> expected<T> +{ + return expected<T>( unexpected_type<std::exception_ptr>( std::forward<std::exception_ptr>( v ) ) ); +} + +template< typename T, typename E > +constexpr auto make_expected_from_error( E e ) -> expected<T, typename std::decay<E>::type> +{ + return expected<T, typename std::decay<E>::type>( make_unexpected( e ) ); +} + +template< typename F > +/*nsel_constexpr14*/ +auto make_expected_from_call( F f, + nsel_REQUIRES( ! std::is_same<typename std::result_of<F()>::type, void>::value ) +) -> expected< typename std::result_of<F()>::type > +{ + try + { + return make_expected( f() ); + } + catch (...) + { + return make_unexpected_from_current_exception(); + } +} + +template< typename F > +/*nsel_constexpr14*/ +auto make_expected_from_call( F f, + nsel_REQUIRES( std::is_same<typename std::result_of<F()>::type, void>::value ) +) -> expected<void> +{ + try + { + f(); + return make_expected(); + } + catch (...) + { + return make_unexpected_from_current_exception(); + } +} + +#endif // nsel_P0323R + +} // namespace nonstd + +namespace std { + +// expected: hash support + +template< typename T, typename E > +struct hash< nonstd::expected<T,E> > +{ + using result_type = typename hash<T>::result_type; + using argument_type = nonstd::expected<T,E>; + + constexpr result_type operator()(argument_type const & arg) const + { + return arg ? std::hash<T>{}(*arg) : result_type{}; + } +}; + +// TBD - ?? remove? see spec. +template< typename T, typename E > +struct hash< nonstd::expected<T&,E> > +{ + using result_type = typename hash<T>::result_type; + using argument_type = nonstd::expected<T&,E>; + + constexpr result_type operator()(argument_type const & arg) const + { + return arg ? std::hash<T>{}(*arg) : result_type{}; + } +}; + +// TBD - implement +// bool(e), hash<expected<void,E>>()(e) shall evaluate to the hashing true; +// otherwise it evaluates to an unspecified value if E is exception_ptr or +// a combination of hashing false and hash<E>()(e.error()). + +template< typename E > +struct hash< nonstd::expected<void,E> > +{ +}; + +} // namespace std + + +namespace nonstd { + +// void unexpected() is deprecated && removed in C++17 + +#if nsel_CPP17_OR_GREATER && nsel_COMPILER_MSVC_VERSION > 141 +template< typename E > +using unexpected = unexpected_type<E>; +#endif + +} // namespace nonstd + +#undef nsel_REQUIRES +#undef nsel_REQUIRES_0 +#undef nsel_REQUIRES_T + +nsel_RESTORE_WARNINGS() + +#endif // NONSTD_EXPECTED_LITE_HPP diff --git a/vendor/expected/version.txt b/vendor/expected/version.txt new file mode 100644 index 0000000000..52e4107440 --- /dev/null +++ b/vendor/expected/version.txt @@ -0,0 +1 @@ +a2359cf61478d735a308e952b1c9840714f61386 |