From d1fe196bb5a3d29a132f20ef27a993c74fb72433 Mon Sep 17 00:00:00 2001 From: tqcq <99722391+tqcq@users.noreply.github.com> Date: Fri, 14 Jun 2024 12:44:44 +0800 Subject: [PATCH] feat update optional --- src/sled/cleanup.h | 2 +- src/sled/config.cc | 24 +- src/sled/config.h | 4 +- src/sled/nonstd/expected.h | 5476 +++++++++++++++++-------------- src/sled/operations_chain.h | 8 +- src/sled/optional.h | 6 + src/sled/status_or.h | 2 +- src/sled/system/hot_reloader.cc | 6 +- src/sled/system/hot_reloader.h | 2 +- src/sled/variant.h | 3641 ++++++++++---------- 10 files changed, 4701 insertions(+), 4470 deletions(-) diff --git a/src/sled/cleanup.h b/src/sled/cleanup.h index 5cc1fa5..a522b49 100644 --- a/src/sled/cleanup.h +++ b/src/sled/cleanup.h @@ -50,7 +50,7 @@ public: } private: - sled::optional callback_; + tl::optional callback_; }; template diff --git a/src/sled/config.cc b/src/sled/config.cc index 6c81ba9..e19b01d 100644 --- a/src/sled/config.cc +++ b/src/sled/config.cc @@ -256,16 +256,16 @@ Config::AddDefaultNode(sled::string_view key, ValueType value) auto first_key = keys[0]; switch (value.index()) { case 0: - toml_[first_key] = sled::get(value); + toml_[first_key] = mpark::get(value); break; case 1: - toml_[first_key] = sled::get(value); + toml_[first_key] = mpark::get(value); break; case 2: - toml_[first_key] = sled::get(value); + toml_[first_key] = mpark::get(value); break; case 3: - toml_[first_key] = sled::get(value); + toml_[first_key] = mpark::get(value); break; default: return false; @@ -284,16 +284,16 @@ Config::GetValueNode(sled::string_view key, toml::value &value) const auto &default_value = iter->second; switch (default_value.index()) { case 0: - value = sled::get(default_value); + value = mpark::get(default_value); break; case 1: - value = sled::get(default_value); + value = mpark::get(default_value); break; case 2: - value = sled::get(default_value); + value = mpark::get(default_value); break; case 3: - value = sled::get(default_value); + value = mpark::get(default_value); break; default: return false; @@ -309,16 +309,16 @@ Config::GetDefaultNode(sled::string_view key, toml::value &value) const auto &default_value = iter->second; switch (default_value.index()) { case 0: - value = sled::get(default_value); + value = mpark::get(default_value); break; case 1: - value = sled::get(default_value); + value = mpark::get(default_value); break; case 2: - value = sled::get(default_value); + value = mpark::get(default_value); break; case 3: - value = sled::get(default_value); + value = mpark::get(default_value); break; default: return false; diff --git a/src/sled/config.h b/src/sled/config.h index 332c63f..e7954c2 100644 --- a/src/sled/config.h +++ b/src/sled/config.h @@ -8,9 +8,9 @@ namespace sled { class Config { public: - using ValueType = sled::variant; + using ValueType = mpark::variant; Config(); - virtual ~Config()=default; + virtual ~Config() = default; Config(sled::string_view name); Config(sled::string_view name, sled::string_view path); Config(const Config &lhs) = delete; diff --git a/src/sled/nonstd/expected.h b/src/sled/nonstd/expected.h index c4e816e..c7057f4 100644 --- a/src/sled/nonstd/expected.h +++ b/src/sled/nonstd/expected.h @@ -1,2613 +1,3067 @@ -/// -// expected - An implementation of std::expected with extensions -// Written in 2017 by Sy Brand (tartanllama@gmail.com, @TartanLlama) +// This version targets C++11 and later. // -// Documentation available at http://tl.tartanllama.xyz/ +// Copyright (C) 2016-2020 Martin Moene. // -// To the extent possible under law, the author(s) have dedicated all -// copyright and related and neighboring rights to this software to the -// public domain worldwide. This software is distributed without any warranty. +// 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) // -// You should have received a copy of the CC0 Public Domain Dedication -// along with this software. If not, see -// . -/// +// 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 TL_EXPECTED_HPP -#define TL_EXPECTED_HPP +#ifndef NONSTD_EXPECTED_LITE_HPP +#define NONSTD_EXPECTED_LITE_HPP -#define TL_EXPECTED_VERSION_MAJOR 1 -#define TL_EXPECTED_VERSION_MINOR 1 -#define TL_EXPECTED_VERSION_PATCH 0 +#define expected_lite_MAJOR 0 +#define expected_lite_MINOR 6 +#define expected_lite_PATCH 3 +#define expected_lite_VERSION \ + expected_STRINGIFY(expected_lite_MAJOR) "." expected_STRINGIFY( \ + expected_lite_MINOR) "." expected_STRINGIFY(expected_lite_PATCH) + +#define expected_STRINGIFY(x) expected_STRINGIFY_(x) +#define expected_STRINGIFY_(x) #x + +// expected-lite configuration: + +#define nsel_EXPECTED_DEFAULT 0 +#define nsel_EXPECTED_NONSTD 1 +#define nsel_EXPECTED_STD 2 + +// tweak header support: + +#ifdef __has_include +#if __has_include() +#include +#endif +#define expected_HAVE_TWEAK_HEADER 1 +#else +#define expected_HAVE_TWEAK_HEADER 0 +// # pragma message("expected.hpp: Note: Tweak header not supported.") +#endif + +// expected selection and configuration: + +#if !defined(nsel_CONFIG_SELECT_EXPECTED) +#define nsel_CONFIG_SELECT_EXPECTED \ + (nsel_HAVE_STD_EXPECTED ? nsel_EXPECTED_STD : nsel_EXPECTED_NONSTD) +#endif + +// Proposal revisions: +// +// 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) +// P0323R6: 6 (2018-04-02) +// P0323R7: 7 (2018-06-22) * +// +// expected-lite uses 2 and higher + +#ifndef nsel_P0323R +#define nsel_P0323R 7 +#endif + +// Monadic operations proposal revisions: +// +// P2505R0: 0 (2021-12-12) +// P2505R1: 1 (2022-02-10) +// P2505R2: 2 (2022-04-15) +// P2505R3: 3 (2022-06-05) +// P2505R4: 4 (2022-06-15) +// P2505R5: 5 (2022-09-20) * +// +// expected-lite uses 5 + +#ifndef nsel_P2505R +#define nsel_P2505R 5 +#endif + +// Control presence of C++ exception handling (try and auto discover): + +#ifndef nsel_CONFIG_NO_EXCEPTIONS +#if defined(_MSC_VER) +#include // for _HAS_EXCEPTIONS +#endif +#if defined(__cpp_exceptions) || defined(__EXCEPTIONS) || (_HAS_EXCEPTIONS) +#define nsel_CONFIG_NO_EXCEPTIONS 0 +#else +#define nsel_CONFIG_NO_EXCEPTIONS 1 +#endif +#endif + +// at default use SEH with MSVC for no C++ exceptions + +#ifndef nsel_CONFIG_NO_EXCEPTIONS_SEH +#define nsel_CONFIG_NO_EXCEPTIONS_SEH (nsel_CONFIG_NO_EXCEPTIONS && _MSC_VER) +#endif + +// C++ language version detection (C++23 is speculative): +// Note: VC14.0/1900 (VS2015) lacks too much from C++14. + +#ifndef nsel_CPLUSPLUS +#if defined(_MSVC_LANG) && !defined(__clang__) +#define nsel_CPLUSPLUS (_MSC_VER == 1900 ? 201103L : _MSVC_LANG) +#else +#define nsel_CPLUSPLUS __cplusplus +#endif +#endif + +#define nsel_CPP98_OR_GREATER (nsel_CPLUSPLUS >= 199711L) +#define nsel_CPP11_OR_GREATER (nsel_CPLUSPLUS >= 201103L) +#define nsel_CPP14_OR_GREATER (nsel_CPLUSPLUS >= 201402L) +#define nsel_CPP17_OR_GREATER (nsel_CPLUSPLUS >= 201703L) +#define nsel_CPP20_OR_GREATER (nsel_CPLUSPLUS >= 202002L) +#define nsel_CPP23_OR_GREATER (nsel_CPLUSPLUS >= 202300L) + +// Use C++23 std::expected if available and requested: + +#if nsel_CPP23_OR_GREATER && defined(__has_include) +#if __has_include( ) +#define nsel_HAVE_STD_EXPECTED 1 +#else +#define nsel_HAVE_STD_EXPECTED 0 +#endif +#else +#define nsel_HAVE_STD_EXPECTED 0 +#endif + +#define nsel_USES_STD_EXPECTED \ + ((nsel_CONFIG_SELECT_EXPECTED == nsel_EXPECTED_STD) || \ + ((nsel_CONFIG_SELECT_EXPECTED == nsel_EXPECTED_DEFAULT) && \ + nsel_HAVE_STD_EXPECTED)) + +// +// in_place: code duplicated in any-lite, expected-lite, expected-lite, +// value-ptr-lite, variant-lite: +// + +#ifndef nonstd_lite_HAVE_IN_PLACE_TYPES +#define nonstd_lite_HAVE_IN_PLACE_TYPES 1 + +// C++17 std::in_place in : + +#if nsel_CPP17_OR_GREATER + +#include + +namespace nonstd { + +using std::in_place; +using std::in_place_index; +using std::in_place_index_t; +using std::in_place_t; +using std::in_place_type; +using std::in_place_type_t; + +#define nonstd_lite_in_place_t(T) std::in_place_t +#define nonstd_lite_in_place_type_t(T) std::in_place_type_t +#define nonstd_lite_in_place_index_t(K) std::in_place_index_t + +#define nonstd_lite_in_place(T) \ + std::in_place_t {} +#define nonstd_lite_in_place_type(T) \ + std::in_place_type_t {} +#define nonstd_lite_in_place_index(K) \ + std::in_place_index_t {} + +} // namespace nonstd + +#else // nsel_CPP17_OR_GREATER + +#include + +namespace nonstd { +namespace detail { + +template struct in_place_type_tag {}; + +template struct in_place_index_tag {}; + +} // namespace detail + +struct in_place_t {}; + +template +inline in_place_t +in_place(detail::in_place_type_tag = detail::in_place_type_tag()) { + return in_place_t(); +} + +template +inline in_place_t +in_place(detail::in_place_index_tag = detail::in_place_index_tag()) { + return in_place_t(); +} + +template +inline in_place_t +in_place_type(detail::in_place_type_tag = detail::in_place_type_tag()) { + return in_place_t(); +} + +template +inline in_place_t in_place_index( + detail::in_place_index_tag = detail::in_place_index_tag()) { + return in_place_t(); +} + +// mimic templated typedef: + +#define nonstd_lite_in_place_t(T) \ + nonstd::in_place_t (&)(nonstd::detail::in_place_type_tag) +#define nonstd_lite_in_place_type_t(T) \ + nonstd::in_place_t (&)(nonstd::detail::in_place_type_tag) +#define nonstd_lite_in_place_index_t(K) \ + nonstd::in_place_t (&)(nonstd::detail::in_place_index_tag) + +#define nonstd_lite_in_place(T) nonstd::in_place_type +#define nonstd_lite_in_place_type(T) nonstd::in_place_type +#define nonstd_lite_in_place_index(K) nonstd::in_place_index + +} // namespace nonstd + +#endif // nsel_CPP17_OR_GREATER +#endif // nonstd_lite_HAVE_IN_PLACE_TYPES + +// +// Using std::expected: +// + +#if nsel_USES_STD_EXPECTED + +#include + +namespace nonstd { + +using std::expected; +// ... +} // namespace nonstd + +#else // nsel_USES_STD_EXPECTED + +#include #include #include +#include +#include +#include +#include #include #include -#if defined(__EXCEPTIONS) || defined(_CPPUNWIND) -#define TL_EXPECTED_EXCEPTIONS_ENABLED -#endif +// additional includes: -#if (defined(_MSC_VER) && _MSC_VER == 1900) -#define TL_EXPECTED_MSVC2015 -#define TL_EXPECTED_MSVC2015_CONSTEXPR +#if nsel_CONFIG_NO_EXCEPTIONS +#if nsel_CONFIG_NO_EXCEPTIONS_SEH +#include // for ExceptionCodes #else -#define TL_EXPECTED_MSVC2015_CONSTEXPR constexpr +// already included: #endif - -#if (defined(__GNUC__) && __GNUC__ == 4 && __GNUC_MINOR__ <= 9 && !defined(__clang__)) -#define TL_EXPECTED_GCC49 -#endif - -#if (defined(__GNUC__) && __GNUC__ == 5 && __GNUC_MINOR__ <= 4 && !defined(__clang__)) -#define TL_EXPECTED_GCC54 -#endif - -#if (defined(__GNUC__) && __GNUC__ == 5 && __GNUC_MINOR__ <= 5 && !defined(__clang__)) -#define TL_EXPECTED_GCC55 -#endif - -#if !defined(TL_ASSERT) -//can't have assert in constexpr in C++11 and GCC 4.9 has a compiler bug -#if (__cplusplus > 201103L) && !defined(TL_EXPECTED_GCC49) -#include -#define TL_ASSERT(x) assert(x) #else -#define TL_ASSERT(x) -#endif +#include #endif -#if (defined(__GNUC__) && __GNUC__ == 4 && __GNUC_MINOR__ <= 9 && !defined(__clang__)) -// GCC < 5 doesn't support overloading on const&& for member functions +// C++ feature usage: -#define TL_EXPECTED_NO_CONSTRR -// GCC < 5 doesn't support some standard C++11 type traits -#define TL_EXPECTED_IS_TRIVIALLY_COPY_CONSTRUCTIBLE(T) std::has_trivial_copy_constructor -#define TL_EXPECTED_IS_TRIVIALLY_COPY_ASSIGNABLE(T) std::has_trivial_copy_assign - -// This one will be different for GCC 5.7 if it's ever supported -#define TL_EXPECTED_IS_TRIVIALLY_DESTRUCTIBLE(T) std::is_trivially_destructible - -// GCC 5 < v < 8 has a bug in is_trivially_copy_constructible which breaks -// std::vector for non-copyable types -#elif (defined(__GNUC__) && __GNUC__ < 8 && !defined(__clang__)) -#ifndef TL_GCC_LESS_8_TRIVIALLY_COPY_CONSTRUCTIBLE_MUTEX -#define TL_GCC_LESS_8_TRIVIALLY_COPY_CONSTRUCTIBLE_MUTEX - -namespace tl { -namespace detail { -template -struct is_trivially_copy_constructible : std::is_trivially_copy_constructible {}; -#ifdef _GLIBCXX_VECTOR -template -struct is_trivially_copy_constructible> : std::false_type {}; -#endif -}// namespace detail -}// namespace tl -#endif - -#define TL_EXPECTED_IS_TRIVIALLY_COPY_CONSTRUCTIBLE(T) tl::detail::is_trivially_copy_constructible -#define TL_EXPECTED_IS_TRIVIALLY_COPY_ASSIGNABLE(T) std::is_trivially_copy_assignable -#define TL_EXPECTED_IS_TRIVIALLY_DESTRUCTIBLE(T) std::is_trivially_destructible +#if nsel_CPP11_OR_GREATER +#define nsel_constexpr constexpr #else -#define TL_EXPECTED_IS_TRIVIALLY_COPY_CONSTRUCTIBLE(T) std::is_trivially_copy_constructible -#define TL_EXPECTED_IS_TRIVIALLY_COPY_ASSIGNABLE(T) std::is_trivially_copy_assignable -#define TL_EXPECTED_IS_TRIVIALLY_DESTRUCTIBLE(T) std::is_trivially_destructible +#define nsel_constexpr /*constexpr*/ #endif -#if __cplusplus > 201103L -#define TL_EXPECTED_CXX14 -#endif - -#ifdef TL_EXPECTED_GCC49 -#define TL_EXPECTED_GCC49_CONSTEXPR +#if nsel_CPP14_OR_GREATER +#define nsel_constexpr14 constexpr #else -#define TL_EXPECTED_GCC49_CONSTEXPR constexpr +#define nsel_constexpr14 /*constexpr*/ #endif -#if (__cplusplus == 201103L || defined(TL_EXPECTED_MSVC2015) || defined(TL_EXPECTED_GCC49)) -#define TL_EXPECTED_11_CONSTEXPR +#if nsel_CPP17_OR_GREATER +#define nsel_inline17 inline #else -#define TL_EXPECTED_11_CONSTEXPR constexpr +#define nsel_inline17 /*inline*/ #endif -namespace tl { -template -class expected; - -#ifndef TL_MONOSTATE_INPLACE_MUTEX -#define TL_MONOSTATE_INPLACE_MUTEX - -class monostate {}; - -struct in_place_t { - explicit in_place_t() = default; -}; - -static constexpr in_place_t in_place{}; -#endif - -template -class unexpected { -public: - static_assert(!std::is_same::value, "E must not be void"); - - unexpected() = delete; - - constexpr explicit unexpected(const E &e) : m_val(e) {} - - constexpr explicit unexpected(E &&e) : m_val(std::move(e)) {} - - template::value>::type * = nullptr> - constexpr explicit unexpected(Args &&...args) : m_val(std::forward(args)...) - {} - - template &, Args &&...>::value>::type - * = nullptr> - constexpr explicit unexpected(std::initializer_list l, Args &&...args) : m_val(l, std::forward(args)...) - {} - - constexpr const E &value() const & { return m_val; } - - TL_EXPECTED_11_CONSTEXPR E &value() & { return m_val; } - - TL_EXPECTED_11_CONSTEXPR E &&value() && { return std::move(m_val); } - - constexpr const E &&value() const && { return std::move(m_val); } - -private: - E m_val; -}; - -#ifdef __cpp_deduction_guides -template -unexpected(E) -> unexpected; -#endif - -template -constexpr bool -operator==(const unexpected &lhs, const unexpected &rhs) -{ - return lhs.value() == rhs.value(); -} - -template -constexpr bool -operator!=(const unexpected &lhs, const unexpected &rhs) -{ - return lhs.value() != rhs.value(); -} - -template -constexpr bool -operator<(const unexpected &lhs, const unexpected &rhs) -{ - return lhs.value() < rhs.value(); -} - -template -constexpr bool -operator<=(const unexpected &lhs, const unexpected &rhs) -{ - return lhs.value() <= rhs.value(); -} - -template -constexpr bool -operator>(const unexpected &lhs, const unexpected &rhs) -{ - return lhs.value() > rhs.value(); -} - -template -constexpr bool -operator>=(const unexpected &lhs, const unexpected &rhs) -{ - return lhs.value() >= rhs.value(); -} - -template -unexpected::type> -make_unexpected(E &&e) -{ - return unexpected::type>(std::forward(e)); -} - -struct unexpect_t { - unexpect_t() = default; -}; - -static constexpr unexpect_t unexpect{}; - -namespace detail { -template -[[noreturn]] TL_EXPECTED_11_CONSTEXPR void -throw_exception(E &&e) -{ -#ifdef TL_EXPECTED_EXCEPTIONS_ENABLED - throw std::forward(e); -#else - (void) e; -#ifdef _MSC_VER - __assume(0); -#else - __builtin_unreachable(); -#endif -#endif -} - -#ifndef TL_TRAITS_MUTEX -#define TL_TRAITS_MUTEX -// C++14-style aliases for brevity -template -using remove_const_t = typename std::remove_const::type; -template -using remove_reference_t = typename std::remove_reference::type; -template -using decay_t = typename std::decay::type; -template -using enable_if_t = typename std::enable_if::type; -template -using conditional_t = typename std::conditional::type; - -// std::conjunction from C++17 -template -struct conjunction : std::true_type {}; - -template -struct conjunction : B {}; - -template -struct conjunction : std::conditional, B>::type {}; - -#if defined(_LIBCPP_VERSION) && __cplusplus == 201103L -#define TL_TRAITS_LIBCXX_MEM_FN_WORKAROUND -#endif - -// In C++11 mode, there's an issue in libc++'s std::mem_fn -// which results in a hard-error when using it in a noexcept expression -// in some cases. This is a check to workaround the common failing case. -#ifdef TL_TRAITS_LIBCXX_MEM_FN_WORKAROUND -template -struct is_pointer_to_non_const_member_func : std::false_type {}; - -template -struct is_pointer_to_non_const_member_func : std::true_type {}; - -template -struct is_pointer_to_non_const_member_func : std::true_type {}; - -template -struct is_pointer_to_non_const_member_func : std::true_type {}; - -template -struct is_pointer_to_non_const_member_func : std::true_type {}; - -template -struct is_pointer_to_non_const_member_func : std::true_type {}; - -template -struct is_pointer_to_non_const_member_func : std::true_type {}; - -template -struct is_const_or_const_ref : std::false_type {}; - -template -struct is_const_or_const_ref : std::true_type {}; - -template -struct is_const_or_const_ref : std::true_type {}; -#endif - -// std::invoke from C++17 -// https://stackoverflow.com/questions/38288042/c11-14-invoke-workaround -template::value && is_const_or_const_ref::value)>, -#endif - typename = enable_if_t>::value>, - int = 0> -constexpr auto -invoke(Fn &&f, Args &&...args) noexcept(noexcept(std::mem_fn(f)(std::forward(args)...))) - -> decltype(std::mem_fn(f)(std::forward(args)...)) -{ - return std::mem_fn(f)(std::forward(args)...); -} - -template>::value>> -constexpr auto -invoke(Fn &&f, Args &&...args) noexcept(noexcept(std::forward(f)(std::forward(args)...))) - -> decltype(std::forward(f)(std::forward(args)...)) -{ - return std::forward(f)(std::forward(args)...); -} - -// std::invoke_result from C++17 -template -struct invoke_result_impl; - -template -struct invoke_result_impl(), std::declval()...), void()), Us...> { - using type = decltype(detail::invoke(std::declval(), std::declval()...)); -}; - -template -using invoke_result = invoke_result_impl; - -template -using invoke_result_t = typename invoke_result::type; - -#if defined(_MSC_VER) && _MSC_VER <= 1900 -// TODO make a version which works with MSVC 2015 -template -struct is_swappable : std::true_type {}; - -template -struct is_nothrow_swappable : std::true_type {}; -#else -// https://stackoverflow.com/questions/26744589/what-is-a-proper-way-to-implement-is-swappable-to-test-for-the-swappable-concept -namespace swap_adl_tests { -// if swap ADL finds this then it would call std::swap otherwise (same -// signature) -struct tag {}; - -template -tag swap(T &, T &); -template -tag swap(T (&a)[N], T (&b)[N]); - -// helper functions to test if an unqualified swap is possible, and if it -// becomes std::swap -template -std::false_type can_swap(...) noexcept(false); -template(), std::declval()))> -std::true_type can_swap(int) noexcept(noexcept(swap(std::declval(), std::declval()))); - -template -std::false_type uses_std(...); -template -std::is_same(), std::declval())), tag> uses_std(int); - -template -struct is_std_swap_noexcept - : std::integral_constant::value - && std::is_nothrow_move_assignable::value> {}; - -template -struct is_std_swap_noexcept : is_std_swap_noexcept {}; - -template -struct is_adl_swap_noexcept : std::integral_constant(0))> {}; -}// namespace swap_adl_tests - -template -struct is_swappable - : std::integral_constant(0))::value - && (!decltype(detail::swap_adl_tests::uses_std(0))::value - || (std::is_move_assignable::value && std::is_move_constructible::value))> { -}; - -template -struct is_swappable - : std::integral_constant(0))::value - && (!decltype(detail::swap_adl_tests::uses_std(0))::value - || is_swappable::value)> {}; - -template -struct is_nothrow_swappable - : std::integral_constant::value - && ((decltype(detail::swap_adl_tests::uses_std(0))::value - && detail::swap_adl_tests::is_std_swap_noexcept::value) - || (!decltype(detail::swap_adl_tests::uses_std(0))::value - && detail::swap_adl_tests::is_adl_swap_noexcept::value))> {}; -#endif -#endif - -// Trait for checking if a type is a tl::expected -template -struct is_expected_impl : std::false_type {}; - -template -struct is_expected_impl> : std::true_type {}; -template -using is_expected = is_expected_impl>; - -template -using expected_enable_forward_value - = detail::enable_if_t::value && !std::is_same, in_place_t>::value - && !std::is_same, detail::decay_t>::value - && !std::is_same, detail::decay_t>::value>; - -template -using expected_enable_from_other = detail::enable_if_t< - std::is_constructible::value && std::is_constructible::value - && !std::is_constructible &>::value && !std::is_constructible &&>::value - && !std::is_constructible &>::value - && !std::is_constructible &&>::value && !std::is_convertible &, T>::value - && !std::is_convertible &&, T>::value && !std::is_convertible &, T>::value - && !std::is_convertible &&, T>::value>; - -template -using is_void_or = conditional_t::value, std::true_type, U>; - -template -using is_copy_constructible_or_void = is_void_or>; - -template -using is_move_constructible_or_void = is_void_or>; - -template -using is_copy_assignable_or_void = is_void_or>; - -template -using is_move_assignable_or_void = is_void_or>; - -}// namespace detail - -namespace detail { -struct no_init_t {}; - -static constexpr no_init_t no_init{}; - -// Implements the storage of the values, and ensures that the destructor is -// trivial if it can be. +// Compiler versions: // -// This specialization is for where neither `T` or `E` is trivially -// destructible, so the destructors must be called on destruction of the -// `expected` -template::value, - bool = std::is_trivially_destructible::value> -struct expected_storage_base { - constexpr expected_storage_base() : m_val(T{}), m_has_val(true) {} +// MSVC++ 6.0 _MSC_VER == 1200 nsel_COMPILER_MSVC_VERSION == 60 (Visual +// Studio 6.0) MSVC++ 7.0 _MSC_VER == 1300 nsel_COMPILER_MSVC_VERSION == 70 +// (Visual Studio .NET 2002) MSVC++ 7.1 _MSC_VER == 1310 +// nsel_COMPILER_MSVC_VERSION == 71 (Visual Studio .NET 2003) MSVC++ 8.0 +// _MSC_VER == 1400 nsel_COMPILER_MSVC_VERSION == 80 (Visual Studio 2005) +// MSVC++ 9.0 _MSC_VER == 1500 nsel_COMPILER_MSVC_VERSION == 90 (Visual +// Studio 2008) MSVC++ 10.0 _MSC_VER == 1600 nsel_COMPILER_MSVC_VERSION == 100 +// (Visual Studio 2010) MSVC++ 11.0 _MSC_VER == 1700 nsel_COMPILER_MSVC_VERSION +// == 110 (Visual Studio 2012) MSVC++ 12.0 _MSC_VER == 1800 +// nsel_COMPILER_MSVC_VERSION == 120 (Visual Studio 2013) MSVC++ 14.0 _MSC_VER +// == 1900 nsel_COMPILER_MSVC_VERSION == 140 (Visual Studio 2015) MSVC++ 14.1 +// _MSC_VER >= 1910 nsel_COMPILER_MSVC_VERSION == 141 (Visual Studio 2017) +// MSVC++ 14.2 _MSC_VER >= 1920 nsel_COMPILER_MSVC_VERSION == 142 (Visual +// Studio 2019) - constexpr expected_storage_base(no_init_t) : m_no_init(), m_has_val(false) {} - - template::value> * = nullptr> - constexpr expected_storage_base(in_place_t, Args &&...args) - : m_val(std::forward(args)...), - m_has_val(true) - {} - - template &, Args &&...>::value> * = nullptr> - constexpr expected_storage_base(in_place_t, std::initializer_list il, Args &&...args) - : m_val(il, std::forward(args)...), - m_has_val(true) - {} - - template::value> * = nullptr> - constexpr explicit expected_storage_base(unexpect_t, Args &&...args) - : m_unexpect(std::forward(args)...), - m_has_val(false) - {} - - template &, Args &&...>::value> * = nullptr> - constexpr explicit expected_storage_base(unexpect_t, std::initializer_list il, Args &&...args) - : m_unexpect(il, std::forward(args)...), - m_has_val(false) - {} - - ~expected_storage_base() - { - if (m_has_val) { - m_val.~T(); - } else { - m_unexpect.~unexpected(); - } - } - - union { - T m_val; - unexpected m_unexpect; - char m_no_init; - }; - - bool m_has_val; -}; - -// This specialization is for when both `T` and `E` are trivially-destructible, -// so the destructor of the `expected` can be trivial. -template -struct expected_storage_base { - constexpr expected_storage_base() : m_val(T{}), m_has_val(true) {} - - constexpr expected_storage_base(no_init_t) : m_no_init(), m_has_val(false) {} - - template::value> * = nullptr> - constexpr expected_storage_base(in_place_t, Args &&...args) - : m_val(std::forward(args)...), - m_has_val(true) - {} - - template &, Args &&...>::value> * = nullptr> - constexpr expected_storage_base(in_place_t, std::initializer_list il, Args &&...args) - : m_val(il, std::forward(args)...), - m_has_val(true) - {} - - template::value> * = nullptr> - constexpr explicit expected_storage_base(unexpect_t, Args &&...args) - : m_unexpect(std::forward(args)...), - m_has_val(false) - {} - - template &, Args &&...>::value> * = nullptr> - constexpr explicit expected_storage_base(unexpect_t, std::initializer_list il, Args &&...args) - : m_unexpect(il, std::forward(args)...), - m_has_val(false) - {} - - ~expected_storage_base() = default; - - union { - T m_val; - unexpected m_unexpect; - char m_no_init; - }; - - bool m_has_val; -}; - -// T is trivial, E is not. -template -struct expected_storage_base { - constexpr expected_storage_base() : m_val(T{}), m_has_val(true) {} - - TL_EXPECTED_MSVC2015_CONSTEXPR expected_storage_base(no_init_t) : m_no_init(), m_has_val(false) {} - - template::value> * = nullptr> - constexpr expected_storage_base(in_place_t, Args &&...args) - : m_val(std::forward(args)...), - m_has_val(true) - {} - - template &, Args &&...>::value> * = nullptr> - constexpr expected_storage_base(in_place_t, std::initializer_list il, Args &&...args) - : m_val(il, std::forward(args)...), - m_has_val(true) - {} - - template::value> * = nullptr> - constexpr explicit expected_storage_base(unexpect_t, Args &&...args) - : m_unexpect(std::forward(args)...), - m_has_val(false) - {} - - template &, Args &&...>::value> * = nullptr> - constexpr explicit expected_storage_base(unexpect_t, std::initializer_list il, Args &&...args) - : m_unexpect(il, std::forward(args)...), - m_has_val(false) - {} - - ~expected_storage_base() - { - if (!m_has_val) { m_unexpect.~unexpected(); } - } - - union { - T m_val; - unexpected m_unexpect; - char m_no_init; - }; - - bool m_has_val; -}; - -// E is trivial, T is not. -template -struct expected_storage_base { - constexpr expected_storage_base() : m_val(T{}), m_has_val(true) {} - - constexpr expected_storage_base(no_init_t) : m_no_init(), m_has_val(false) {} - - template::value> * = nullptr> - constexpr expected_storage_base(in_place_t, Args &&...args) - : m_val(std::forward(args)...), - m_has_val(true) - {} - - template &, Args &&...>::value> * = nullptr> - constexpr expected_storage_base(in_place_t, std::initializer_list il, Args &&...args) - : m_val(il, std::forward(args)...), - m_has_val(true) - {} - - template::value> * = nullptr> - constexpr explicit expected_storage_base(unexpect_t, Args &&...args) - : m_unexpect(std::forward(args)...), - m_has_val(false) - {} - - template &, Args &&...>::value> * = nullptr> - constexpr explicit expected_storage_base(unexpect_t, std::initializer_list il, Args &&...args) - : m_unexpect(il, std::forward(args)...), - m_has_val(false) - {} - - ~expected_storage_base() - { - if (m_has_val) { m_val.~T(); } - } - - union { - T m_val; - unexpected m_unexpect; - char m_no_init; - }; - - bool m_has_val; -}; - -// `T` is `void`, `E` is trivially-destructible -template -struct expected_storage_base { -#if __GNUC__ <= 5 -//no constexpr for GCC 4/5 bug +#if defined(_MSC_VER) && !defined(__clang__) +#define nsel_COMPILER_MSVC_VER (_MSC_VER) +#define nsel_COMPILER_MSVC_VERSION \ + (_MSC_VER / 10 - 10 * (5 + (_MSC_VER < 1900))) #else - TL_EXPECTED_MSVC2015_CONSTEXPR +#define nsel_COMPILER_MSVC_VER 0 +#define nsel_COMPILER_MSVC_VERSION 0 #endif - expected_storage_base() : m_has_val(true) {} - constexpr expected_storage_base(no_init_t) : m_val(), m_has_val(false) {} +#define nsel_COMPILER_VERSION(major, minor, patch) \ + (10 * (10 * (major) + (minor)) + (patch)) - constexpr expected_storage_base(in_place_t) : m_has_val(true) {} +#if defined(__clang__) +#define nsel_COMPILER_CLANG_VERSION \ + nsel_COMPILER_VERSION(__clang_major__, __clang_minor__, __clang_patchlevel__) +#else +#define nsel_COMPILER_CLANG_VERSION 0 +#endif - template::value> * = nullptr> - constexpr explicit expected_storage_base(unexpect_t, Args &&...args) - : m_unexpect(std::forward(args)...), - m_has_val(false) - {} +#if defined(__GNUC__) && !defined(__clang__) +#define nsel_COMPILER_GNUC_VERSION \ + nsel_COMPILER_VERSION(__GNUC__, __GNUC_MINOR__, __GNUC_PATCHLEVEL__) +#else +#define nsel_COMPILER_GNUC_VERSION 0 +#endif - template &, Args &&...>::value> * = nullptr> - constexpr explicit expected_storage_base(unexpect_t, std::initializer_list il, Args &&...args) - : m_unexpect(il, std::forward(args)...), - m_has_val(false) - {} +// half-open range [lo..hi): +// #define nsel_BETWEEN( v, lo, hi ) ( (lo) <= (v) && (v) < (hi) ) - ~expected_storage_base() = default; +// Method enabling - struct dummy {}; +#define nsel_REQUIRES_0(...) \ + template ::type = 0> - union { - unexpected m_unexpect; - dummy m_val; - }; +#define nsel_REQUIRES_T(...) \ + , typename std::enable_if<(__VA_ARGS__), int>::type = 0 - bool m_has_val; -}; +#define nsel_REQUIRES_R(R, ...) typename std::enable_if<(__VA_ARGS__), R>::type -// `T` is `void`, `E` is not trivially-destructible -template -struct expected_storage_base { - constexpr expected_storage_base() : m_dummy(), m_has_val(true) {} +#define nsel_REQUIRES_A(...) \ + , typename std::enable_if<(__VA_ARGS__), void *>::type = nullptr - constexpr expected_storage_base(no_init_t) : m_dummy(), m_has_val(false) {} +// Presence of language and library features: - constexpr expected_storage_base(in_place_t) : m_dummy(), m_has_val(true) {} +#ifdef _HAS_CPP0X +#define nsel_HAS_CPP0X _HAS_CPP0X +#else +#define nsel_HAS_CPP0X 0 +#endif - template::value> * = nullptr> - constexpr explicit expected_storage_base(unexpect_t, Args &&...args) - : m_unexpect(std::forward(args)...), - m_has_val(false) - {} +// #define nsel_CPP11_140 (nsel_CPP11_OR_GREATER || nsel_COMPILER_MSVC_VER >= +// 1900) - template &, Args &&...>::value> * = nullptr> - constexpr explicit expected_storage_base(unexpect_t, std::initializer_list il, Args &&...args) - : m_unexpect(il, std::forward(args)...), - m_has_val(false) - {} +// Clang, GNUC, MSVC warning suppression macros: - ~expected_storage_base() - { - if (!m_has_val) { m_unexpect.~unexpected(); } - } +#ifdef __clang__ +#pragma clang diagnostic push +#elif defined __GNUC__ +#pragma GCC diagnostic push +#endif // __clang__ - union { - unexpected m_unexpect; - char m_dummy; - }; +#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 - bool m_has_val; -}; +#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 -// This base class provides some handy member functions which can be used in -// further derived classes -template -struct expected_operations_base : expected_storage_base { - using expected_storage_base::expected_storage_base; +// Suppress the following MSVC (GSL) warnings: +// - C26409: Avoid calling new and delete explicitly, use std::make_unique +// instead (r.11) - template - void construct(Args &&...args) noexcept - { - new (std::addressof(this->m_val)) T(std::forward(args)...); - this->m_has_val = true; - } +nsel_DISABLE_MSVC_WARNINGS(26409) - template - void construct_with(Rhs &&rhs) noexcept - { - new (std::addressof(this->m_val)) T(std::forward(rhs).get()); - this->m_has_val = true; - } - - template - void construct_error(Args &&...args) noexcept - { - new (std::addressof(this->m_unexpect)) unexpected(std::forward(args)...); - this->m_has_val = false; - } - -#ifdef TL_EXPECTED_EXCEPTIONS_ENABLED - - // These assign overloads ensure that the most efficient assignment - // implementation is used while maintaining the strong exception guarantee. - // The problematic case is where rhs has a value, but *this does not. // - // This overload handles the case where we can just copy-construct `T` - // directly into place without throwing. - template::value> * = nullptr> - void assign(const expected_operations_base &rhs) noexcept - { - if (!this->m_has_val && rhs.m_has_val) { - geterr().~unexpected(); - construct(rhs.get()); - } else { - assign_common(rhs); - } + // expected: + // + + namespace nonstd { + namespace expected_lite { + + // type traits C++17: + + namespace std17 { + +#if nsel_CPP17_OR_GREATER + + using std::conjunction; + using std::is_nothrow_swappable; + using std::is_swappable; + +#else // nsel_CPP17_OR_GREATER + + namespace detail { + + using std::swap; + + struct is_swappable { + template (), + std::declval()))> + static std::true_type test(int /* unused */); + + template static std::false_type test(...); + }; + + struct is_nothrow_swappable { + // wrap noexcept(expr) in separate function as work-around for VC140 + // (VS2015): + + template static constexpr bool satisfies() { + return noexcept(swap(std::declval(), std::declval())); } - // This overload handles the case where we can attempt to create a copy of - // `T`, then no-throw move it into place if the copy was successful. - template::value - && std::is_nothrow_move_constructible::value> * = nullptr> - void assign(const expected_operations_base &rhs) noexcept - { - if (!this->m_has_val && rhs.m_has_val) { - T tmp = rhs.get(); - geterr().~unexpected(); - construct(std::move(tmp)); - } else { - assign_common(rhs); - } - } + template + static auto test(int) -> std::integral_constant()> {} - // This overload is the worst-case, where we have to move-construct the - // unexpected value into temporary storage, then try to copy the T into place. - // If the construction succeeds, then everything is fine, but if it throws, - // then we move the old unexpected value back into place before rethrowing the - // exception. - template::value - && !std::is_nothrow_move_constructible::value> * = nullptr> - void assign(const expected_operations_base &rhs) - { - if (!this->m_has_val && rhs.m_has_val) { - auto tmp = std::move(geterr()); - geterr().~unexpected(); + template static auto test(...) -> std::false_type; + }; + } // namespace detail -#ifdef TL_EXPECTED_EXCEPTIONS_ENABLED - try { - construct(rhs.get()); - } catch (...) { - geterr() = std::move(tmp); - throw; - } -#else - construct(rhs.get()); -#endif - } else { - assign_common(rhs); - } - } + // is [nothrow] swappable: - // These overloads do the same as above, but for rvalues - template::value> * = nullptr> - void assign(expected_operations_base &&rhs) noexcept - { - if (!this->m_has_val && rhs.m_has_val) { - geterr().~unexpected(); - construct(std::move(rhs).get()); - } else { - assign_common(std::move(rhs)); - } - } + template + struct is_swappable : decltype(detail::is_swappable::test(0)) {}; - template::value> * = nullptr> - void assign(expected_operations_base &&rhs) - { - if (!this->m_has_val && rhs.m_has_val) { - auto tmp = std::move(geterr()); - geterr().~unexpected(); -#ifdef TL_EXPECTED_EXCEPTIONS_ENABLED - try { - construct(std::move(rhs).get()); - } catch (...) { - geterr() = std::move(tmp); - throw; - } -#else - construct(std::move(rhs).get()); -#endif - } else { - assign_common(std::move(rhs)); - } - } + template + struct is_nothrow_swappable + : decltype(detail::is_nothrow_swappable::test(0)) {}; + + // conjunction: + + template struct conjunction : std::true_type {}; + template struct conjunction : B1 {}; + + template + struct conjunction + : std::conditional, B1>::type {}; + +#endif // nsel_CPP17_OR_GREATER + + } // namespace std17 + + // type traits C++20: + + namespace std20 { + +#if defined(__cpp_lib_remove_cvref) + + using std::remove_cvref; #else - // If exceptions are disabled then we can just copy-construct - void assign(const expected_operations_base &rhs) noexcept - { - if (!this->m_has_val && rhs.m_has_val) { - geterr().~unexpected(); - construct(rhs.get()); - } else { - assign_common(rhs); - } - } - - void assign(expected_operations_base &&rhs) noexcept - { - if (!this->m_has_val && rhs.m_has_val) { - geterr().~unexpected(); - construct(std::move(rhs).get()); - } else { - assign_common(std::move(rhs)); - } - } + template struct remove_cvref { + typedef + typename std::remove_cv::type>::type + type; + }; #endif - // The common part of move/copy assigning - template - void assign_common(Rhs &&rhs) - { - if (this->m_has_val) { - if (rhs.m_has_val) { - get() = std::forward(rhs).get(); - } else { - destroy_val(); - construct_error(std::forward(rhs).geterr()); - } - } else { - if (!rhs.m_has_val) { geterr() = std::forward(rhs).geterr(); } - } + } // namespace std20 + + // forward declaration: + + template class expected; + + namespace detail { + +#if nsel_P2505R >= 3 + template struct is_expected : std::false_type {}; + + template + struct is_expected> : std::true_type {}; +#endif // nsel_P2505R >= 3 + + /// discriminated union to hold value or 'error'. + + template class storage_t_noncopy_nonmove_impl { + template friend class nonstd::expected_lite::expected; + + public: + using value_type = T; + using error_type = E; + + // no-op construction + storage_t_noncopy_nonmove_impl() {} + ~storage_t_noncopy_nonmove_impl() {} + + explicit storage_t_noncopy_nonmove_impl(bool has_value) + : m_has_value(has_value) {} + + void construct_value() { new (&m_value) value_type(); } + + // void construct_value( value_type const & e ) + // { + // new( &m_value ) value_type( e ); + // } + + // void construct_value( value_type && e ) + // { + // new( &m_value ) value_type( std::move( e ) ); + // } + + template void emplace_value(Args &&...args) { + new (&m_value) value_type(std::forward(args)...); } - bool has_value() const { return this->m_has_val; } - - TL_EXPECTED_11_CONSTEXPR T &get() & { return this->m_val; } - - constexpr const T &get() const & { return this->m_val; } - - TL_EXPECTED_11_CONSTEXPR T &&get() && { return std::move(this->m_val); } -#ifndef TL_EXPECTED_NO_CONSTRR - constexpr const T &&get() const && { return std::move(this->m_val); } -#endif - - TL_EXPECTED_11_CONSTEXPR unexpected &geterr() & { return this->m_unexpect; } - - constexpr const unexpected &geterr() const & { return this->m_unexpect; } - - TL_EXPECTED_11_CONSTEXPR unexpected &&geterr() && { return std::move(this->m_unexpect); } -#ifndef TL_EXPECTED_NO_CONSTRR - constexpr const unexpected &&geterr() const && { return std::move(this->m_unexpect); } -#endif - - TL_EXPECTED_11_CONSTEXPR void destroy_val() { get().~T(); } -}; - -// This base class provides some handy member functions which can be used in -// further derived classes -template -struct expected_operations_base : expected_storage_base { - using expected_storage_base::expected_storage_base; - - template - void construct() noexcept - { - this->m_has_val = true; + template + void emplace_value(std::initializer_list il, Args &&...args) { + new (&m_value) value_type(il, std::forward(args)...); } - // This function doesn't use its argument, but needs it so that code in - // levels above this can work independently of whether T is void - template - void construct_with(Rhs &&) noexcept - { - this->m_has_val = true; + 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 ) ); + // } + + template void emplace_error(Args &&...args) { + new (&m_error) error_type(std::forward(args)...); } - template - void construct_error(Args &&...args) noexcept - { - new (std::addressof(this->m_unexpect)) unexpected(std::forward(args)...); - this->m_has_val = false; + template + void emplace_error(std::initializer_list il, Args &&...args) { + new (&m_error) error_type(il, std::forward(args)...); } - template - void assign(Rhs &&rhs) noexcept - { - if (!this->m_has_val) { - if (rhs.m_has_val) { - geterr().~unexpected(); - construct(); - } else { - geterr() = std::forward(rhs).geterr(); - } - } else { - if (!rhs.m_has_val) { construct_error(std::forward(rhs).geterr()); } - } + 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; } + + constexpr error_type const &&error() const && { return std::move(m_error); } + + nsel_constexpr14 error_type &&error() && { return std::move(m_error); } + + bool has_value() const { return m_has_value; } + + void set_has_value(bool v) { m_has_value = v; } + + private: + union { + value_type m_value; + error_type m_error; + }; + + bool m_has_value = false; + }; + + template class storage_t_impl { + template friend class nonstd::expected_lite::expected; + + public: + using value_type = T; + using error_type = E; + + // no-op construction + storage_t_impl() {} + ~storage_t_impl() {} + + explicit storage_t_impl(bool has_value) : m_has_value(has_value) {} + + void construct_value() { new (&m_value) value_type(); } + + void construct_value(value_type const &e) { new (&m_value) value_type(e); } + + void construct_value(value_type &&e) { + new (&m_value) value_type(std::move(e)); } - bool has_value() const { return this->m_has_val; } - - TL_EXPECTED_11_CONSTEXPR unexpected &geterr() & { return this->m_unexpect; } - - constexpr const unexpected &geterr() const & { return this->m_unexpect; } - - TL_EXPECTED_11_CONSTEXPR unexpected &&geterr() && { return std::move(this->m_unexpect); } -#ifndef TL_EXPECTED_NO_CONSTRR - constexpr const unexpected &&geterr() const && { return std::move(this->m_unexpect); } -#endif - - TL_EXPECTED_11_CONSTEXPR void destroy_val() - { - // no-op - } -}; - -// This class manages conditionally having a trivial copy constructor -// This specialization is for when T and E are trivially copy constructible -template::value - && TL_EXPECTED_IS_TRIVIALLY_COPY_CONSTRUCTIBLE(E)::value> -struct expected_copy_base : expected_operations_base { - using expected_operations_base::expected_operations_base; -}; - -// This specialization is for when T or E are not trivially copy constructible -template -struct expected_copy_base : expected_operations_base { - using expected_operations_base::expected_operations_base; - - expected_copy_base() = default; - - expected_copy_base(const expected_copy_base &rhs) : expected_operations_base(no_init) - { - if (rhs.has_value()) { - this->construct_with(rhs); - } else { - this->construct_error(rhs.geterr()); - } + template void emplace_value(Args &&...args) { + new (&m_value) value_type(std::forward(args)...); } - expected_copy_base(expected_copy_base &&rhs) = default; - expected_copy_base &operator=(const expected_copy_base &rhs) = default; - expected_copy_base &operator=(expected_copy_base &&rhs) = default; -}; + template + void emplace_value(std::initializer_list il, Args &&...args) { + new (&m_value) value_type(il, std::forward(args)...); + } -// This class manages conditionally having a trivial move constructor -// Unfortunately there's no way to achieve this in GCC < 5 AFAIK, since it -// doesn't implement an analogue to std::is_trivially_move_constructible. We -// have to make do with a non-trivial move constructor even if T is trivially -// move constructible -#ifndef TL_EXPECTED_GCC49 -template>::value - && std::is_trivially_move_constructible::value> -struct expected_move_base : expected_copy_base { - using expected_copy_base::expected_copy_base; -}; + 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)); + } + + template void emplace_error(Args &&...args) { + new (&m_error) error_type(std::forward(args)...); + } + + template + void emplace_error(std::initializer_list il, Args &&...args) { + new (&m_error) error_type(il, std::forward(args)...); + } + + 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; } + + constexpr error_type const &&error() const && { return std::move(m_error); } + + nsel_constexpr14 error_type &&error() && { return std::move(m_error); } + + bool has_value() const { return m_has_value; } + + void set_has_value(bool v) { m_has_value = v; } + + private: + union { + value_type m_value; + error_type m_error; + }; + + bool m_has_value = false; + }; + + /// discriminated union to hold only 'error'. + + template struct storage_t_impl { + template friend class nonstd::expected_lite::expected; + + public: + using value_type = void; + using error_type = E; + + // no-op construction + storage_t_impl() {} + ~storage_t_impl() {} + + explicit storage_t_impl(bool has_value) : m_has_value(has_value) {} + + 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)); + } + + template void emplace_error(Args &&...args) { + new (&m_error) error_type(std::forward(args)...); + } + + template + void emplace_error(std::initializer_list il, Args &&...args) { + new (&m_error) error_type(il, std::forward(args)...); + } + + void destruct_error() { m_error.~error_type(); } + + error_type const &error() const & { return m_error; } + + error_type &error() & { return m_error; } + + constexpr error_type const &&error() const && { return std::move(m_error); } + + nsel_constexpr14 error_type &&error() && { return std::move(m_error); } + + bool has_value() const { return m_has_value; } + + void set_has_value(bool v) { m_has_value = v; } + + private: + union { + char m_dummy; + error_type m_error; + }; + + bool m_has_value = false; + }; + + template + class storage_t { + public: + }; + + template + class storage_t + : public storage_t_noncopy_nonmove_impl { + public: + storage_t() = default; + ~storage_t() = default; + + explicit storage_t(bool has_value) + : storage_t_noncopy_nonmove_impl(has_value) {} + + storage_t(storage_t const &other) = delete; + storage_t(storage_t &&other) = delete; + }; + + template + class storage_t : public storage_t_impl { + public: + storage_t() = default; + ~storage_t() = default; + + explicit storage_t(bool has_value) : storage_t_impl(has_value) {} + + storage_t(storage_t const &other) + : storage_t_impl(other.has_value()) { + if (this->has_value()) + this->construct_value(other.value()); + else + this->construct_error(other.error()); + } + + storage_t(storage_t &&other) : storage_t_impl(other.has_value()) { + if (this->has_value()) + this->construct_value(std::move(other.value())); + else + this->construct_error(std::move(other.error())); + } + }; + + template + class storage_t : public storage_t_impl { + public: + storage_t() = default; + ~storage_t() = default; + + explicit storage_t(bool has_value) : storage_t_impl(has_value) {} + + storage_t(storage_t const &other) + : storage_t_impl(other.has_value()) { + if (this->has_value()) + ; + else + this->construct_error(other.error()); + } + + storage_t(storage_t &&other) : storage_t_impl(other.has_value()) { + if (this->has_value()) + ; + else + this->construct_error(std::move(other.error())); + } + }; + + template + class storage_t : public storage_t_impl { + public: + storage_t() = default; + ~storage_t() = default; + + explicit storage_t(bool has_value) : storage_t_impl(has_value) {} + + storage_t(storage_t const &other) + : storage_t_impl(other.has_value()) { + if (this->has_value()) + this->construct_value(other.value()); + else + this->construct_error(other.error()); + } + + storage_t(storage_t &&other) = delete; + }; + + template + class storage_t : public storage_t_impl { + public: + storage_t() = default; + ~storage_t() = default; + + explicit storage_t(bool has_value) : storage_t_impl(has_value) {} + + storage_t(storage_t const &other) + : storage_t_impl(other.has_value()) { + if (this->has_value()) + ; + else + this->construct_error(other.error()); + } + + storage_t(storage_t &&other) = delete; + }; + + template + class storage_t : public storage_t_impl { + public: + storage_t() = default; + ~storage_t() = default; + + explicit storage_t(bool has_value) : storage_t_impl(has_value) {} + + storage_t(storage_t const &other) = delete; + + storage_t(storage_t &&other) : storage_t_impl(other.has_value()) { + if (this->has_value()) + this->construct_value(std::move(other.value())); + else + this->construct_error(std::move(other.error())); + } + }; + + template + class storage_t : public storage_t_impl { + public: + storage_t() = default; + ~storage_t() = default; + + explicit storage_t(bool has_value) : storage_t_impl(has_value) {} + + storage_t(storage_t const &other) = delete; + + storage_t(storage_t &&other) : storage_t_impl(other.has_value()) { + if (this->has_value()) + ; + else + this->construct_error(std::move(other.error())); + } + }; + +#if nsel_P2505R >= 3 + // C++11 invoke implementation + template struct is_reference_wrapper : std::false_type {}; + template + struct is_reference_wrapper> : std::true_type {}; + + template < + typename FnT, typename ClassT, typename ObjectT, + typename... Args nsel_REQUIRES_T( + std::is_function::value && + (std::is_same::type>::value || + std::is_base_of< + ClassT, typename std20::remove_cvref::type>::value))> + nsel_constexpr auto invoke_member_function_impl( + FnT ClassT::*memfnptr, ObjectT &&obj, + Args &&...args) noexcept(noexcept((std::forward(obj).* + memfnptr)(std::forward( + args)...))) -> decltype((std::forward(obj).* + memfnptr)(std::forward(args)...)) { + return (std::forward(obj).*memfnptr)(std::forward(args)...); + } + + template ::value &&is_reference_wrapper< + typename std20::remove_cvref::type>::value)> + nsel_constexpr auto + invoke_member_function_impl(FnT ClassT::*memfnptr, ObjectT &&obj, + Args &&...args) noexcept(noexcept((obj.get().* + memfnptr)( + std::forward(args)...))) + -> decltype((obj.get().*memfnptr)(std::forward(args)...)) { + return (obj.get().*memfnptr)(std::forward(args)...); + } + + template < + typename FnT, typename ClassT, typename ObjectT, + typename... Args nsel_REQUIRES_T( + std::is_function::value && + !std::is_same::type>::value && + !std::is_base_of< + ClassT, typename std20::remove_cvref::type>::value && + !is_reference_wrapper< + typename std20::remove_cvref::type>::value)> + nsel_constexpr auto invoke_member_function_impl( + FnT ClassT::*memfnptr, ObjectT &&obj, + Args &&...args) noexcept(noexcept(((*std::forward(obj)).* + memfnptr)(std::forward( + args)...))) -> decltype(((*std::forward(obj)).* + memfnptr)(std::forward(args)...)) { + return ((*std::forward(obj)).* + memfnptr)(std::forward(args)...); + } + + template < + typename MemberT, typename ClassT, + typename ObjectT nsel_REQUIRES_T( + std::is_same::type>::value || + std::is_base_of::type>::value)> + nsel_constexpr auto + invoke_member_object_impl(MemberT ClassT::*memobjptr, ObjectT &&obj) noexcept( + noexcept(std::forward(obj).* + memobjptr)) -> decltype(std::forward(obj).*memobjptr) { + return std::forward(obj).*memobjptr; + } + + template ::type>::value)> + nsel_constexpr auto + invoke_member_object_impl(MemberT ClassT::*memobjptr, ObjectT &&obj) noexcept( + noexcept(obj.get().*memobjptr)) -> decltype(obj.get().*memobjptr) { + return obj.get().*memobjptr; + } + + template < + typename MemberT, typename ClassT, + typename ObjectT nsel_REQUIRES_T( + !std::is_same::type>::value && + !std::is_base_of< + ClassT, typename std20::remove_cvref::type>::value && + !is_reference_wrapper< + typename std20::remove_cvref::type>::value)> + nsel_constexpr auto + invoke_member_object_impl(MemberT ClassT::*memobjptr, ObjectT &&obj) noexcept( + noexcept((*std::forward(obj)).*memobjptr)) + -> decltype((*std::forward(obj)).*memobjptr) { + return (*std::forward(obj)).*memobjptr; + } + + template ::type>::value)> + nsel_constexpr auto invoke(F &&f, Args &&...args) noexcept( + noexcept(invoke_member_function_impl(std::forward(f), + std::forward(args)...))) + -> decltype(invoke_member_function_impl(std::forward(f), + std::forward(args)...)) { + return invoke_member_function_impl(std::forward(f), + std::forward(args)...); + } + + template ::type>::value)> + nsel_constexpr auto invoke(F &&f, Args &&...args) noexcept( + noexcept(invoke_member_object_impl(std::forward(f), + std::forward(args)...))) + -> decltype(invoke_member_object_impl(std::forward(f), + std::forward(args)...)) { + return invoke_member_object_impl(std::forward(f), + std::forward(args)...); + } + + template ::type>::value && + !std::is_member_object_pointer< + typename std20::remove_cvref::type>::value)> + nsel_constexpr auto invoke(F &&f, Args &&...args) noexcept( + noexcept(std::forward(f)(std::forward(args)...))) + -> decltype(std::forward(f)(std::forward(args)...)) { + return std::forward(f)(std::forward(args)...); + } + + template + using invoke_result_nocvref_t = typename std20::remove_cvref(), std::declval()...))>::type; + +#if nsel_P2505R >= 5 + template + using transform_invoke_result_t = typename std::remove_cv(), std::declval()...))>::type; #else -template -struct expected_move_base; -#endif -template -struct expected_move_base : expected_copy_base { - using expected_copy_base::expected_copy_base; + template + using transform_invoke_result_t = invoke_result_nocvref_t +#endif // nsel_P2505R >= 5 - expected_move_base() = default; - expected_move_base(const expected_move_base &rhs) = default; + template + struct valid_expected_value_type + : std::integral_constant::value && + !std::is_reference::value && + !std::is_array::value> {}; - expected_move_base(expected_move_base &&rhs) noexcept(std::is_nothrow_move_constructible::value) - : expected_copy_base(no_init) - { - if (rhs.has_value()) { - this->construct_with(std::move(rhs)); - } else { - this->construct_error(std::move(rhs.geterr())); - } - } +#endif // nsel_P2505R >= 3 + } // namespace detail - expected_move_base &operator=(const expected_move_base &rhs) = default; - expected_move_base &operator=(expected_move_base &&rhs) = default; -}; + /// x.x.5 Unexpected object type; unexpected_type; C++17 and later can also + /// use aliased type unexpected. -// This class manages conditionally having a trivial copy assignment operator -template>::value - && TL_EXPECTED_IS_TRIVIALLY_COPY_ASSIGNABLE(E)::value - && TL_EXPECTED_IS_TRIVIALLY_COPY_CONSTRUCTIBLE(E)::value && TL_EXPECTED_IS_TRIVIALLY_DESTRUCTIBLE(E)::value> -struct expected_copy_assign_base : expected_move_base { - using expected_move_base::expected_move_base; -}; - -template -struct expected_copy_assign_base : expected_move_base { - using expected_move_base::expected_move_base; - - expected_copy_assign_base() = default; - expected_copy_assign_base(const expected_copy_assign_base &rhs) = default; - - expected_copy_assign_base(expected_copy_assign_base &&rhs) = default; - - expected_copy_assign_base &operator=(const expected_copy_assign_base &rhs) - { - this->assign(rhs); - return *this; - } - - expected_copy_assign_base &operator=(expected_copy_assign_base &&rhs) = default; -}; - -// This class manages conditionally having a trivial move assignment operator -// Unfortunately there's no way to achieve this in GCC < 5 AFAIK, since it -// doesn't implement an analogue to std::is_trivially_move_assignable. We have -// to make do with a non-trivial move assignment operator even if T is trivially -// move assignable -#ifndef TL_EXPECTED_GCC49 -template, - std::is_trivially_move_constructible, - std::is_trivially_move_assignable>>::value - && std::is_trivially_destructible::value && std::is_trivially_move_constructible::value - && std::is_trivially_move_assignable::value> -struct expected_move_assign_base : expected_copy_assign_base { - using expected_copy_assign_base::expected_copy_assign_base; -}; +#if nsel_P0323R <= 2 + template + class unexpected_type #else -template -struct expected_move_assign_base; + template + class unexpected_type +#endif // nsel_P0323R + { + public: + using error_type = E; + + // x.x.5.2.1 Constructors + + // unexpected_type() = delete; + + constexpr unexpected_type(unexpected_type const &) = default; + constexpr unexpected_type(unexpected_type &&) = default; + + template ::value)> + constexpr explicit unexpected_type(nonstd_lite_in_place_t(E), + Args &&...args) + : m_error(std::forward(args)...) {} + + template , + Args &&...>::value)> + constexpr explicit unexpected_type(nonstd_lite_in_place_t(E), + std::initializer_list il, + Args &&...args) + : m_error(il, std::forward(args)...) {} + + template ::value && + !std::is_same::type, + nonstd_lite_in_place_t(E2)>::value && + !std::is_same::type, + unexpected_type>::value)> + constexpr explicit unexpected_type(E2 &&error) + : m_error(std::forward(error)) {} + + template ::value && + !std::is_constructible &>::value && + !std::is_constructible>::value && + !std::is_constructible const &>::value && + !std::is_constructible const>::value && + !std::is_convertible &, E>::value && + !std::is_convertible, E>::value && + !std::is_convertible const &, E>::value && + !std::is_convertible const, E>::value && + !std::is_convertible::value /*=> explicit */ + )> + constexpr explicit unexpected_type(unexpected_type const &error) + : m_error(E{error.value()}) {} + + template ::value && + !std::is_constructible &>::value && + !std::is_constructible>::value && + !std::is_constructible const &>::value && + !std::is_constructible const>::value && + !std::is_convertible &, E>::value && + !std::is_convertible, E>::value && + !std::is_convertible const &, E>::value && + !std::is_convertible const, E>::value && + std::is_convertible::value /*=> explicit */ + )> + constexpr /*non-explicit*/ unexpected_type(unexpected_type const &error) + : m_error(error.value()) {} + + template ::value && + !std::is_constructible &>::value && + !std::is_constructible>::value && + !std::is_constructible const &>::value && + !std::is_constructible const>::value && + !std::is_convertible &, E>::value && + !std::is_convertible, E>::value && + !std::is_convertible const &, E>::value && + !std::is_convertible const, E>::value && + !std::is_convertible::value /*=> explicit */ + )> + constexpr explicit unexpected_type(unexpected_type &&error) + : m_error(E{std::move(error.value())}) {} + + template ::value && + !std::is_constructible &>::value && + !std::is_constructible>::value && + !std::is_constructible const &>::value && + !std::is_constructible const>::value && + !std::is_convertible &, E>::value && + !std::is_convertible, E>::value && + !std::is_convertible const &, E>::value && + !std::is_convertible const, E>::value && + std::is_convertible::value /*=> non-explicit */ + )> + constexpr /*non-explicit*/ unexpected_type(unexpected_type &&error) + : m_error(std::move(error.value())) {} + + // x.x.5.2.2 Assignment + + nsel_constexpr14 unexpected_type & + operator=(unexpected_type const &) = default; + nsel_constexpr14 unexpected_type &operator=(unexpected_type &&) = default; + + template + nsel_constexpr14 unexpected_type & + operator=(unexpected_type const &other) { + unexpected_type{other.value()}.swap(*this); + return *this; + } + + template + nsel_constexpr14 unexpected_type &operator=(unexpected_type &&other) { + unexpected_type{std::move(other.value())}.swap(*this); + return *this; + } + + // x.x.5.2.3 Observers + + nsel_constexpr14 E &value() & noexcept { return m_error; } + + constexpr E const &value() const & noexcept { return m_error; } + +#if !nsel_COMPILER_GNUC_VERSION || nsel_COMPILER_GNUC_VERSION >= 490 + + nsel_constexpr14 E &&value() && noexcept { return std::move(m_error); } + + constexpr E const &&value() const && noexcept { return std::move(m_error); } + #endif -template -struct expected_move_assign_base : expected_copy_assign_base { - using expected_copy_assign_base::expected_copy_assign_base; + // x.x.5.2.4 Swap - expected_move_assign_base() = default; - expected_move_assign_base(const expected_move_assign_base &rhs) = default; - - expected_move_assign_base(expected_move_assign_base &&rhs) = default; - - expected_move_assign_base &operator=(const expected_move_assign_base &rhs) = default; - - expected_move_assign_base &operator=(expected_move_assign_base &&rhs) noexcept( - std::is_nothrow_move_constructible::value && std::is_nothrow_move_assignable::value) - { - this->assign(std::move(rhs)); - return *this; + template + nsel_REQUIRES_R(void, std17::is_swappable::value) + swap(unexpected_type &other) noexcept( + std17::is_nothrow_swappable::value) { + using std::swap; + swap(m_error, other.m_error); } + + // TODO: ??? unexpected_type: in-class friend operator==, != + + private: + error_type m_error; + }; + +#if nsel_CPP17_OR_GREATER + + /// template deduction guide: + + template unexpected_type(E) -> unexpected_type; + +#endif + + /// class unexpected_type, std::exception_ptr specialization (P0323R2) + +#if !nsel_CONFIG_NO_EXCEPTIONS +#if nsel_P0323R <= 2 + + // TODO: Should expected be specialized for particular E types such as + // exception_ptr and how? + // See p0323r7 2.1. Ergonomics, http://wg21.link/p0323 + template <> class unexpected_type { + 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 + 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 +#endif // !nsel_CONFIG_NO_EXCEPTIONS + + /// x.x.4, Unexpected equality operators + + template + constexpr bool operator==(unexpected_type const &x, + unexpected_type const &y) { + return x.value() == y.value(); + } + + template + constexpr bool operator!=(unexpected_type const &x, + unexpected_type const &y) { + return !(x == y); + } + +#if nsel_P0323R <= 2 + + template + constexpr bool operator<(unexpected_type const &x, + unexpected_type const &y) { + return x.value() < y.value(); + } + + template + constexpr bool operator>(unexpected_type const &x, + unexpected_type const &y) { + return (y < x); + } + + template + constexpr bool operator<=(unexpected_type const &x, + unexpected_type const &y) { + return !(y < x); + } + + template + constexpr bool operator>=(unexpected_type const &x, + unexpected_type const &y) { + return !(x < y); + } + +#endif // nsel_P0323R + + /// x.x.5 Specialized algorithms + + template ::value)> + void swap(unexpected_type &x, + unexpected_type &y) noexcept(noexcept(x.swap(y))) { + x.swap(y); + } + +#if nsel_P0323R <= 2 + + // unexpected: relational operators for std::exception_ptr: + + inline constexpr bool + operator<(unexpected_type const & /*x*/, + unexpected_type const & /*y*/) { + return false; + } + + inline constexpr bool + operator>(unexpected_type const & /*x*/, + unexpected_type const & /*y*/) { + return false; + } + + inline constexpr bool + operator<=(unexpected_type const &x, + unexpected_type const &y) { + return (x == y); + } + + inline constexpr bool + operator>=(unexpected_type const &x, + unexpected_type const &y) { + return (x == y); + } + +#endif // nsel_P0323R + + // unexpected: traits + +#if nsel_P0323R <= 3 + + template struct is_unexpected : std::false_type {}; + + template + struct is_unexpected> : std::true_type {}; + +#endif // nsel_P0323R + + // unexpected: factory + + // keep make_unexpected() removed in p0323r2 for pre-C++17: + + template + nsel_constexpr14 auto + make_unexpected(E &&value) -> unexpected_type::type> { + return unexpected_type::type>( + std::forward(value)); + } + +#if nsel_P0323R <= 3 + + /*nsel_constexpr14*/ auto inline make_unexpected_from_current_exception() + -> unexpected_type { + return unexpected_type(std::current_exception()); + } + +#endif // nsel_P0323R + + /// x.x.6, x.x.7 expected access error + + template class bad_expected_access; + + /// x.x.7 bad_expected_access: expected access error + + template <> class bad_expected_access : public std::exception { + public: + explicit bad_expected_access() : std::exception() {} + }; + + /// x.x.6 bad_expected_access: expected access error + +#if !nsel_CONFIG_NO_EXCEPTIONS + + template + class bad_expected_access : public bad_expected_access { + 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; } + +#if !nsel_COMPILER_GNUC_VERSION || nsel_COMPILER_GNUC_VERSION >= 490 + + nsel_constexpr14 error_type &&error() && { return std::move(m_error); } + + constexpr error_type const &&error() const && { return std::move(m_error); } + +#endif + + private: + error_type m_error; + }; + +#endif // nsel_CONFIG_NO_EXCEPTIONS + + /// x.x.8 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{}; + + /// class error_traits + +#if nsel_CONFIG_NO_EXCEPTIONS + + namespace detail { + inline bool text(char const * /*text*/) { return true; } + } // namespace detail + + template struct error_traits { + static void rethrow(Error const & /*e*/) { +#if nsel_CONFIG_NO_EXCEPTIONS_SEH + RaiseException(EXCEPTION_ACCESS_VIOLATION, EXCEPTION_NONCONTINUABLE, 0, + NULL); +#else + assert(false && detail::text("throw bad_expected_access{ e };")); +#endif + } + }; + + template <> struct error_traits { + static void rethrow(std::exception_ptr const & /*e*/) { +#if nsel_CONFIG_NO_EXCEPTIONS_SEH + RaiseException(EXCEPTION_ACCESS_VIOLATION, EXCEPTION_NONCONTINUABLE, 0, + NULL); +#else + assert( + false && + detail::text("throw bad_expected_access{ e };")); +#endif + } + }; + + template <> struct error_traits { + static void rethrow(std::error_code const & /*e*/) { +#if nsel_CONFIG_NO_EXCEPTIONS_SEH + RaiseException(EXCEPTION_ACCESS_VIOLATION, EXCEPTION_NONCONTINUABLE, 0, + NULL); +#else + assert(false && detail::text("throw std::system_error( e );")); +#endif + } + }; + +#else // nsel_CONFIG_NO_EXCEPTIONS + + template struct error_traits { + static void rethrow(Error const &e) { throw bad_expected_access{e}; } + }; + + template <> struct error_traits { + static void rethrow(std::exception_ptr const &e) { + std::rethrow_exception(e); + } + }; + + template <> struct error_traits { + static void rethrow(std::error_code const &e) { + throw std::system_error(e); + } + }; + +#endif // nsel_CONFIG_NO_EXCEPTIONS + +#if nsel_P2505R >= 3 + namespace detail { + + // from https://en.cppreference.com/w/cpp/utility/expected/unexpected: + // "the type of the unexpected value. The type must not be an array type, a + // non-object type, a specialization of std::unexpected, or a cv-qualified + // type." + template + struct valid_unexpected_type + : std::integral_constant< + bool, + std::is_same::type>::value && + std::is_object::value && !std::is_array::value> {}; + + template + struct valid_unexpected_type> : std::false_type {}; + + } // namespace detail +#endif // nsel_P2505R >= 3 + + } // namespace expected_lite + + // provide nonstd::unexpected_type: + + using expected_lite::unexpected_type; + + namespace expected_lite { + + /// class expected + +#if nsel_P0323R <= 2 + template + class expected +#else + template + class expected +#endif // nsel_P0323R + { + private: + template friend class expected; + + public: + using value_type = T; + using error_type = E; + using unexpected_type = nonstd::unexpected_type; + + template struct rebind { + using type = expected; + }; + + // x.x.4.1 constructors + + nsel_REQUIRES_0(std::is_default_constructible::value) nsel_constexpr14 + expected() + : contained(true) { + contained.construct_value(); + } + + nsel_constexpr14 expected(expected const &) = default; + nsel_constexpr14 expected(expected &&) = default; + + template ::value + &&std::is_constructible::value && + !std::is_constructible &>::value && + !std::is_constructible &&>::value && + !std::is_constructible const &>::value && + !std::is_constructible const &&>::value && + !std::is_convertible &, T>::value && + !std::is_convertible &&, T>::value && + !std::is_convertible const &, T>::value && + !std::is_convertible const &&, T>::value && + (!std::is_convertible::value || + !std::is_convertible::value) /*=> explicit */ + )> + nsel_constexpr14 explicit expected(expected const &other) + : contained(other.has_value()) { + if (has_value()) + contained.construct_value(T{other.contained.value()}); + else + contained.construct_error(E{other.contained.error()}); + } + + template ::value + &&std::is_constructible::value && + !std::is_constructible &>::value && + !std::is_constructible &&>::value && + !std::is_constructible const &>::value && + !std::is_constructible const &&>::value && + !std::is_convertible &, T>::value && + !std::is_convertible &&, T>::value && + !std::is_convertible const &, T>::value && + !std::is_convertible const &&, T>::value && + !(!std::is_convertible::value || + !std::is_convertible::value) /*=> non-explicit + */ + )> + nsel_constexpr14 /*non-explicit*/ expected(expected const &other) + : contained(other.has_value()) { + if (has_value()) + contained.construct_value(other.contained.value()); + else + contained.construct_error(other.contained.error()); + } + + template ::value + &&std::is_constructible::value && + !std::is_constructible &>::value && + !std::is_constructible &&>::value && + !std::is_constructible const &>::value && + !std::is_constructible const &&>::value && + !std::is_convertible &, T>::value && + !std::is_convertible &&, T>::value && + !std::is_convertible const &, T>::value && + !std::is_convertible const &&, T>::value && + (!std::is_convertible::value || + !std::is_convertible::value) /*=> explicit */ + )> + nsel_constexpr14 explicit expected(expected &&other) + : contained(other.has_value()) { + if (has_value()) + contained.construct_value(T{std::move(other.contained.value())}); + else + contained.construct_error(E{std::move(other.contained.error())}); + } + + template ::value + &&std::is_constructible::value && + !std::is_constructible &>::value && + !std::is_constructible &&>::value && + !std::is_constructible const &>::value && + !std::is_constructible const &&>::value && + !std::is_convertible &, T>::value && + !std::is_convertible &&, T>::value && + !std::is_convertible const &, T>::value && + !std::is_convertible const &&, T>::value && + !(!std::is_convertible::value || + !std::is_convertible::value) /*=> non-explicit */ + )> + nsel_constexpr14 /*non-explicit*/ expected(expected &&other) + : contained(other.has_value()) { + if (has_value()) + contained.construct_value(std::move(other.contained.value())); + else + contained.construct_error(std::move(other.contained.error())); + } + + template < + typename U = T nsel_REQUIRES_T(std::is_copy_constructible::value)> + nsel_constexpr14 expected(value_type const &value) : contained(true) { + contained.construct_value(value); + } + + template ::value && + !std::is_same::type, + nonstd_lite_in_place_t(U)>::value && + !std::is_same, + typename std20::remove_cvref::type>::value && + !std::is_same, + typename std20::remove_cvref::type>::value && + !std::is_convertible::value /*=> explicit */ + )> + nsel_constexpr14 explicit expected(U &&value) noexcept( + std::is_nothrow_move_constructible::value && + std::is_nothrow_move_constructible::value) + : contained(true) { + contained.construct_value(T{std::forward(value)}); + } + + template ::value && + !std::is_same::type, + nonstd_lite_in_place_t(U)>::value && + !std::is_same, + typename std20::remove_cvref::type>::value && + !std::is_same, + typename std20::remove_cvref::type>::value && + std::is_convertible::value /*=> non-explicit */ + )> + nsel_constexpr14 /*non-explicit*/ + expected(U &&value) noexcept(std::is_nothrow_move_constructible::value && + std::is_nothrow_move_constructible::value) + : contained(true) { + contained.construct_value(std::forward(value)); + } + + // construct error: + + template ::value && + !std::is_convertible::value /*=> explicit */ + )> + nsel_constexpr14 explicit expected(nonstd::unexpected_type const &error) + : contained(false) { + contained.construct_error(E{error.value()}); + } + + template ::value && + std::is_convertible::value /*=> non-explicit + */ + )> + nsel_constexpr14 /*non-explicit*/ + expected(nonstd::unexpected_type const &error) + : contained(false) { + contained.construct_error(error.value()); + } + + template ::value && + !std::is_convertible::value /*=> explicit */ + )> + nsel_constexpr14 explicit expected(nonstd::unexpected_type &&error) + : contained(false) { + contained.construct_error(E{std::move(error.value())}); + } + + template ::value + &&std::is_convertible::value /*=> non-explicit */ + )> + nsel_constexpr14 /*non-explicit*/ + expected(nonstd::unexpected_type &&error) + : contained(false) { + contained.construct_error(std::move(error.value())); + } + + // in-place construction, value + + template ::value)> + nsel_constexpr14 explicit expected(nonstd_lite_in_place_t(T), + Args &&...args) + : contained(true) { + contained.emplace_value(std::forward(args)...); + } + + template , + Args &&...>::value)> + nsel_constexpr14 explicit expected(nonstd_lite_in_place_t(T), + std::initializer_list il, + Args &&...args) + : contained(true) { + contained.emplace_value(il, std::forward(args)...); + } + + // in-place construction, error + + template ::value)> + nsel_constexpr14 explicit expected(unexpect_t, Args &&...args) + : contained(false) { + contained.emplace_error(std::forward(args)...); + } + + template , + Args &&...>::value)> + nsel_constexpr14 explicit expected(unexpect_t, std::initializer_list il, + Args &&...args) + : contained(false) { + contained.emplace_error(il, std::forward(args)...); + } + + // x.x.4.2 destructor + + // TODO: ~expected: triviality + // Effects: If T is not cv void and is_trivially_destructible_v is false + // and bool(*this), calls val.~T(). If is_trivially_destructible_v is + // false and !bool(*this), calls unexpect.~unexpected(). Remarks: If + // either T is cv void or is_trivially_destructible_v is true, and + // is_trivially_destructible_v is true, then this destructor shall be a + // trivial destructor. + + ~expected() { + if (has_value()) + contained.destruct_value(); + else + contained.destruct_error(); + } + + // x.x.4.3 assignment + + expected &operator=(expected const &other) { + expected(other).swap(*this); + return *this; + } + + expected &operator=(expected &&other) noexcept( + std::is_nothrow_move_constructible::value && + std::is_nothrow_move_assignable::value && + std::is_nothrow_move_constructible::value // added for missing + && std::is_nothrow_move_assignable::value) // nothrow above + { + expected(std::move(other)).swap(*this); + return *this; + } + + template , + typename std20::remove_cvref::type>::value && + std17::conjunction, + std::is_same>>::value && + std::is_constructible::value && + std::is_assignable::value && + std::is_nothrow_move_constructible::value)> + expected &operator=(U &&value) { + expected(std::forward(value)).swap(*this); + return *this; + } + + template ::value + &&std::is_copy_constructible:: + value // TODO: std::is_nothrow_copy_constructible + &&std::is_copy_assignable::value)> + expected &operator=(nonstd::unexpected_type const &error) { + expected(unexpect, error.value()).swap(*this); + return *this; + } + + template < + typename G = E nsel_REQUIRES_T( + std::is_constructible::value &&std::is_move_constructible< + G>::value // TODO: std::is_nothrow_move_constructible + &&std::is_move_assignable::value)> + expected &operator=(nonstd::unexpected_type &&error) { + expected(unexpect, std::move(error.value())).swap(*this); + return *this; + } + + template ::value)> + value_type &emplace(Args &&...args) { + expected(nonstd_lite_in_place(T), std::forward(args)...) + .swap(*this); + return value(); + } + + template &, + Args &&...>::value)> + value_type &emplace(std::initializer_list il, Args &&...args) { + expected(nonstd_lite_in_place(T), il, std::forward(args)...) + .swap(*this); + return value(); + } + + // x.x.4.4 swap + + template + nsel_REQUIRES_R( + void, std17::is_swappable::value &&std17::is_swappable::value && + (std::is_move_constructible::value || + std::is_move_constructible::value)) + swap(expected &other) noexcept( + std::is_nothrow_move_constructible::value && + std17::is_nothrow_swappable::value && + std::is_nothrow_move_constructible::value && + std17::is_nothrow_swappable::value) { + using std::swap; + + if (bool(*this) && bool(other)) { + swap(contained.value(), other.contained.value()); + } else if (!bool(*this) && !bool(other)) { + swap(contained.error(), other.contained.error()); + } else if (bool(*this) && !bool(other)) { + error_type t(std::move(other.error())); + other.contained.destruct_error(); + other.contained.construct_value(std::move(contained.value())); + contained.destruct_value(); + contained.construct_error(std::move(t)); + bool has_value = contained.has_value(); + bool other_has_value = other.has_value(); + other.contained.set_has_value(has_value); + contained.set_has_value(other_has_value); + } else if (!bool(*this) && bool(other)) { + other.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(); } + +#if !nsel_COMPILER_GNUC_VERSION || nsel_COMPILER_GNUC_VERSION >= 490 + + constexpr value_type const &&operator*() const && { + return std::move((assert(has_value()), contained.value())); + } + + nsel_constexpr14 value_type &&operator*() && { + return std::move((assert(has_value()), contained.value())); + } + +#endif + + constexpr explicit operator bool() const noexcept { return has_value(); } + + constexpr bool has_value() const noexcept { return contained.has_value(); } + + constexpr value_type const &value() const & { + return has_value() + ? (contained.value()) + : (error_traits::rethrow(contained.error()), + contained.value()); + } + + value_type &value() & { + return has_value() + ? (contained.value()) + : (error_traits::rethrow(contained.error()), + contained.value()); + } + +#if !nsel_COMPILER_GNUC_VERSION || nsel_COMPILER_GNUC_VERSION >= 490 + + constexpr value_type const &&value() const && { + return std::move( + has_value() ? (contained.value()) + : (error_traits::rethrow(contained.error()), + contained.value())); + } + + nsel_constexpr14 value_type &&value() && { + return std::move( + has_value() ? (contained.value()) + : (error_traits::rethrow(contained.error()), + contained.value())); + } + +#endif + + constexpr error_type const &error() const & { + return assert(!has_value()), contained.error(); + } + + error_type &error() & { return assert(!has_value()), contained.error(); } + +#if !nsel_COMPILER_GNUC_VERSION || nsel_COMPILER_GNUC_VERSION >= 490 + + constexpr error_type const &&error() const && { + return std::move((assert(!has_value()), contained.error())); + } + + error_type &&error() && { + return std::move((assert(!has_value()), contained.error())); + } + +#endif + + constexpr unexpected_type get_unexpected() const { + return make_unexpected(contained.error()); + } + + template bool has_exception() const { + using ContainedEx = typename std::remove_reference< + decltype(get_unexpected().value())>::type; + return !has_value() && std::is_base_of::value; + } + + template < + typename U nsel_REQUIRES_T(std::is_copy_constructible::value + &&std::is_convertible::value)> + value_type value_or(U &&v) const & { + return has_value() ? contained.value() + : static_cast(std::forward(v)); + } + + template < + typename U nsel_REQUIRES_T(std::is_move_constructible::value + &&std::is_convertible::value)> + value_type value_or(U &&v) && { + return has_value() ? std::move(contained.value()) + : static_cast(std::forward(v)); + } + +#if nsel_P2505R >= 4 + template < + typename G = E nsel_REQUIRES_T(std::is_copy_constructible::value + &&std::is_convertible::value)> + nsel_constexpr error_type error_or(G &&e) const & { + return has_value() ? static_cast(std::forward(e)) + : contained.error(); + } + + template < + typename G = E nsel_REQUIRES_T(std::is_move_constructible::value + &&std::is_convertible::value)> + nsel_constexpr14 error_type error_or(G &&e) && { + return has_value() ? static_cast(std::forward(e)) + : std::move(contained.error()); + } +#endif // nsel_P2505R >= 4 + +#if nsel_P2505R >= 3 + // Monadic operations (P2505) + template >:: + value &&std::is_same::error_type, + error_type>::value + &&std::is_constructible::value)> + nsel_constexpr14 detail::invoke_result_nocvref_t + and_then(F &&f) & { + return has_value() ? detail::invoke_result_nocvref_t( + detail::invoke(std::forward(f), value())) + : detail::invoke_result_nocvref_t( + unexpect, error()); + } + + template >::value + &&std::is_same::error_type, + error_type>::value + &&std::is_constructible::value)> + nsel_constexpr detail::invoke_result_nocvref_t + and_then(F &&f) const & { + return has_value() + ? detail::invoke_result_nocvref_t( + detail::invoke(std::forward(f), value())) + : detail::invoke_result_nocvref_t( + unexpect, error()); + } + +#if !nsel_COMPILER_GNUC_VERSION || nsel_COMPILER_GNUC_VERSION >= 490 + template >:: + value &&std::is_same::error_type, + error_type>::value + &&std::is_constructible::value)> + nsel_constexpr14 detail::invoke_result_nocvref_t + and_then(F &&f) && { + return has_value() + ? detail::invoke_result_nocvref_t( + detail::invoke(std::forward(f), std::move(value()))) + : detail::invoke_result_nocvref_t( + unexpect, std::move(error())); + } + + template >::value + &&std::is_same::error_type, + error_type>::value && + std::is_constructible::value)> + nsel_constexpr detail::invoke_result_nocvref_t + and_then(F &&f) const && { + return has_value() + ? detail::invoke_result_nocvref_t( + detail::invoke(std::forward(f), std::move(value()))) + : detail::invoke_result_nocvref_t( + unexpect, std::move(error())); + } +#endif + + template >:: + value &&std::is_same::value_type, + value_type>::value + &&std::is_constructible::value)> + nsel_constexpr14 detail::invoke_result_nocvref_t + or_else(F &&f) & { + return has_value() + ? detail::invoke_result_nocvref_t(value()) + : detail::invoke_result_nocvref_t( + detail::invoke(std::forward(f), error())); + } + + template >::value + &&std::is_same::value_type, + value_type>::value + &&std::is_constructible::value)> + nsel_constexpr detail::invoke_result_nocvref_t + or_else(F &&f) const & { + return has_value() + ? detail::invoke_result_nocvref_t( + value()) + : detail::invoke_result_nocvref_t( + detail::invoke(std::forward(f), error())); + } + +#if !nsel_COMPILER_GNUC_VERSION || nsel_COMPILER_GNUC_VERSION >= 490 + template >:: + value &&std::is_same::value_type, + value_type>::value + &&std::is_constructible::value)> + nsel_constexpr14 detail::invoke_result_nocvref_t + or_else(F &&f) && { + return has_value() + ? detail::invoke_result_nocvref_t( + std::move(value())) + : detail::invoke_result_nocvref_t( + detail::invoke(std::forward(f), std::move(error()))); + } + + template >::value + &&std::is_same::value_type, + value_type>::value && + std::is_constructible::value)> + nsel_constexpr detail::invoke_result_nocvref_t + or_else(F &&f) const && { + return has_value() + ? detail::invoke_result_nocvref_t( + std::move(value())) + : detail::invoke_result_nocvref_t( + detail::invoke(std::forward(f), std::move(error()))); + } +#endif + + template ::value && + !std::is_void< + detail::transform_invoke_result_t>::value && + detail::valid_expected_value_type< + detail::transform_invoke_result_t>::value)> + nsel_constexpr14 + expected, error_type> + transform(F &&f) & { + return has_value() + ? expected, + error_type>( + detail::invoke(std::forward(f), **this)) + : make_unexpected(error()); + } + + template ::value &&std::is_void< + detail::transform_invoke_result_t>::value)> + nsel_constexpr14 expected transform(F &&f) & { + return has_value() ? (detail::invoke(std::forward(f), **this), + expected()) + : make_unexpected(error()); + } + + template ::value && + !std::is_void< + detail::transform_invoke_result_t>::value && + detail::valid_expected_value_type< + detail::transform_invoke_result_t>::value)> + nsel_constexpr + expected, + error_type> + transform(F &&f) const & { + return has_value() + ? expected< + detail::transform_invoke_result_t, + error_type>(detail::invoke(std::forward(f), **this)) + : make_unexpected(error()); + } + + template ::value + &&std::is_void>::value)> + nsel_constexpr expected transform(F &&f) const & { + return has_value() ? (detail::invoke(std::forward(f), **this), + expected()) + : make_unexpected(error()); + } + +#if !nsel_COMPILER_GNUC_VERSION || nsel_COMPILER_GNUC_VERSION >= 490 + template ::value && + !std::is_void< + detail::transform_invoke_result_t>::value && + detail::valid_expected_value_type< + detail::transform_invoke_result_t>::value)> + nsel_constexpr14 + expected, + error_type> + transform(F &&f) && { + return has_value() + ? expected, + error_type>( + detail::invoke(std::forward(f), std::move(**this))) + : make_unexpected(std::move(error())); + } + + template ::value &&std::is_void< + detail::transform_invoke_result_t>::value)> + nsel_constexpr14 expected transform(F &&f) && { + return has_value() ? (detail::invoke(std::forward(f), **this), + expected()) + : make_unexpected(std::move(error())); + } + + template ::value && + !std::is_void< + detail::transform_invoke_result_t>::value && + detail::valid_expected_value_type< + detail::transform_invoke_result_t>::value)> + nsel_constexpr + expected, + error_type> + transform(F &&f) const && { + return has_value() ? expected, + error_type>(detail::invoke( + std::forward(f), std::move(**this))) + : make_unexpected(std::move(error())); + } + + template ::value + &&std::is_void>::value)> + nsel_constexpr expected transform(F &&f) const && { + return has_value() ? (detail::invoke(std::forward(f), **this), + expected()) + : make_unexpected(std::move(error())); + } +#endif + + template >::value + &&std::is_constructible::value)> + nsel_constexpr14 + expected> + transform_error(F &&f) & { + return has_value() + ? expected>( + in_place, **this) + : make_unexpected(detail::invoke(std::forward(f), error())); + } + + template >::value + &&std::is_constructible::value)> + nsel_constexpr + expected> + transform_error(F &&f) const & { + return has_value() + ? expected>(in_place, + **this) + : make_unexpected(detail::invoke(std::forward(f), error())); + } + +#if !nsel_COMPILER_GNUC_VERSION || nsel_COMPILER_GNUC_VERSION >= 490 + template >::value + &&std::is_constructible::value)> + nsel_constexpr14 + expected> + transform_error(F &&f) && { + return has_value() + ? expected>( + in_place, std::move(**this)) + : make_unexpected( + detail::invoke(std::forward(f), std::move(error()))); + } + + template >::value + &&std::is_constructible::value)> + nsel_constexpr + expected> + transform_error(F &&f) const && { + return has_value() + ? expected>( + in_place, std::move(**this)) + : make_unexpected( + detail::invoke(std::forward(f), std::move(error()))); + } +#endif +#endif // nsel_P2505R >= 3 + // unwrap() + + // template + // constexpr expected expected,E>::unwrap() const&; + + // template + // constexpr expected expected::unwrap() const&; + + // template + // expected expected, E>::unwrap() &&; + + // template + // template expected expected::unwrap() &&; + + // factories + + // template< typename Ex, typename F> + // expected catch_exception(F&& f); + + // template< typename F> + // expected())),E> map(F&& func) ; + + // template< typename F> + // 'see below' bind(F&& func); + + // template< typename F> + // expected catch_error(F&& f); + + // template< typename F> + // 'see below' then(F&& func); + + private: + detail::storage_t::value && + std::is_copy_constructible::value, + std::is_move_constructible::value && + std::is_move_constructible::value> + contained; + }; + + /// class expected, void specialization + + template class expected { + private: + template friend class expected; + + public: + using value_type = void; + using error_type = E; + using unexpected_type = nonstd::unexpected_type; + + // x.x.4.1 constructors + + constexpr expected() noexcept : contained(true) {} + + nsel_constexpr14 expected(expected const &other) = default; + nsel_constexpr14 expected(expected &&other) = default; + + constexpr explicit expected(nonstd_lite_in_place_t(void)) + : contained(true) {} + + template ::value /*=> explicit */ + )> + nsel_constexpr14 explicit expected(nonstd::unexpected_type const &error) + : contained(false) { + contained.construct_error(E{error.value()}); + } + + template ::value /*=> non-explicit */ + )> + nsel_constexpr14 /*non-explicit*/ + expected(nonstd::unexpected_type const &error) + : contained(false) { + contained.construct_error(error.value()); + } + + template ::value /*=> explicit */ + )> + nsel_constexpr14 explicit expected(nonstd::unexpected_type &&error) + : contained(false) { + contained.construct_error(E{std::move(error.value())}); + } + + template ::value /*=> non-explicit */ + )> + nsel_constexpr14 /*non-explicit*/ + expected(nonstd::unexpected_type &&error) + : contained(false) { + contained.construct_error(std::move(error.value())); + } + + template ::value)> + nsel_constexpr14 explicit expected(unexpect_t, Args &&...args) + : contained(false) { + contained.emplace_error(std::forward(args)...); + } + + template , + Args &&...>::value)> + nsel_constexpr14 explicit expected(unexpect_t, std::initializer_list il, + Args &&...args) + : contained(false) { + contained.emplace_error(il, std::forward(args)...); + } + + // destructor + + ~expected() { + if (!has_value()) { + contained.destruct_error(); + } + } + + // x.x.4.3 assignment + + expected &operator=(expected const &other) { + expected(other).swap(*this); + return *this; + } + + expected &operator=(expected &&other) noexcept( + std::is_nothrow_move_assignable::value && + std::is_nothrow_move_constructible::value) { + expected(std::move(other)).swap(*this); + return *this; + } + + void emplace() { expected().swap(*this); } + + // x.x.4.4 swap + + template + nsel_REQUIRES_R( + void, + std17::is_swappable::value &&std::is_move_constructible::value) + swap(expected &other) noexcept( + std::is_nothrow_move_constructible::value && + std17::is_nothrow_swappable::value) { + using std::swap; + + if (!bool(*this) && !bool(other)) { + swap(contained.error(), other.contained.error()); + } else if (bool(*this) && !bool(other)) { + contained.construct_error(std::move(other.error())); + bool has_value = contained.has_value(); + bool other_has_value = other.has_value(); + other.contained.set_has_value(has_value); + contained.set_has_value(other_has_value); + } else if (!bool(*this) && bool(other)) { + other.swap(*this); + } + } + + // x.x.4.5 observers + + constexpr explicit operator bool() const noexcept { return has_value(); } + + constexpr bool has_value() const noexcept { return contained.has_value(); } + + void value() const { + if (!has_value()) { + error_traits::rethrow(contained.error()); + } + } + + constexpr error_type const &error() const & { + return assert(!has_value()), contained.error(); + } + + error_type &error() & { return assert(!has_value()), contained.error(); } + +#if !nsel_COMPILER_GNUC_VERSION || nsel_COMPILER_GNUC_VERSION >= 490 + + constexpr error_type const &&error() const && { + return std::move((assert(!has_value()), contained.error())); + } + + error_type &&error() && { + return std::move((assert(!has_value()), contained.error())); + } + +#endif + + constexpr unexpected_type get_unexpected() const { + return make_unexpected(contained.error()); + } + + template bool has_exception() const { + using ContainedEx = typename std::remove_reference< + decltype(get_unexpected().value())>::type; + return !has_value() && std::is_base_of::value; + } + +#if nsel_P2505R >= 4 + template < + typename G = E nsel_REQUIRES_T(std::is_copy_constructible::value + &&std::is_convertible::value)> + nsel_constexpr error_type error_or(G &&e) const & { + return has_value() ? static_cast(std::forward(e)) + : contained.error(); + } + + template < + typename G = E nsel_REQUIRES_T(std::is_move_constructible::value + &&std::is_convertible::value)> + nsel_constexpr14 error_type error_or(G &&e) && { + return has_value() ? static_cast(std::forward(e)) + : std::move(contained.error()); + } +#endif // nsel_P2505R >= 4 + +#if nsel_P2505R >= 3 + // Monadic operations (P2505) + template >::value &&std:: + is_same::error_type, + error_type>::value + &&std::is_constructible::value)> + nsel_constexpr14 detail::invoke_result_nocvref_t and_then(F &&f) & { + return has_value() + ? detail::invoke_result_nocvref_t( + detail::invoke(std::forward(f))) + : detail::invoke_result_nocvref_t(unexpect, error()); + } + + template >::value &&std:: + is_same::error_type, + error_type>::value + &&std::is_constructible::value)> + nsel_constexpr detail::invoke_result_nocvref_t and_then(F &&f) const & { + return has_value() + ? detail::invoke_result_nocvref_t( + detail::invoke(std::forward(f))) + : detail::invoke_result_nocvref_t(unexpect, error()); + } + +#if !nsel_COMPILER_GNUC_VERSION || nsel_COMPILER_GNUC_VERSION >= 490 + template >::value &&std:: + is_same::error_type, + error_type>::value + &&std::is_constructible::value)> + nsel_constexpr14 detail::invoke_result_nocvref_t and_then(F &&f) && { + return has_value() ? detail::invoke_result_nocvref_t( + detail::invoke(std::forward(f))) + : detail::invoke_result_nocvref_t( + unexpect, std::move(error())); + } + + template >::value &&std:: + is_same::error_type, + error_type>::value && + std::is_constructible::value)> + nsel_constexpr detail::invoke_result_nocvref_t and_then(F &&f) const && { + return has_value() ? detail::invoke_result_nocvref_t( + detail::invoke(std::forward(f))) + : detail::invoke_result_nocvref_t( + unexpect, std::move(error())); + } +#endif + + template >:: + value &&std::is_void::value_type>::value)> + nsel_constexpr14 detail::invoke_result_nocvref_t + or_else(F &&f) & { + return has_value() ? detail::invoke_result_nocvref_t() + : detail::invoke_result_nocvref_t( + detail::invoke(std::forward(f), error())); + } + + template >::value + &&std::is_void::value_type>::value)> + nsel_constexpr detail::invoke_result_nocvref_t + or_else(F &&f) const & { + return has_value() + ? detail::invoke_result_nocvref_t() + : detail::invoke_result_nocvref_t( + detail::invoke(std::forward(f), error())); + } + +#if !nsel_COMPILER_GNUC_VERSION || nsel_COMPILER_GNUC_VERSION >= 490 + template >:: + value &&std::is_void::value_type>::value)> + nsel_constexpr14 detail::invoke_result_nocvref_t + or_else(F &&f) && { + return has_value() + ? detail::invoke_result_nocvref_t() + : detail::invoke_result_nocvref_t( + detail::invoke(std::forward(f), std::move(error()))); + } + + template >::value + &&std::is_void::value_type>::value)> + nsel_constexpr detail::invoke_result_nocvref_t + or_else(F &&f) const && { + return has_value() + ? detail::invoke_result_nocvref_t() + : detail::invoke_result_nocvref_t( + detail::invoke(std::forward(f), std::move(error()))); + } +#endif + + template ::value && + !std::is_void>::value)> + nsel_constexpr14 expected, error_type> + transform(F &&f) & { + return has_value() + ? expected, error_type>( + detail::invoke(std::forward(f))) + : make_unexpected(error()); + } + + template ::value + &&std::is_void>::value)> + nsel_constexpr14 expected transform(F &&f) & { + return has_value() ? (detail::invoke(std::forward(f)), + expected()) + : make_unexpected(error()); + } + + template ::value && + !std::is_void>::value)> + nsel_constexpr expected, error_type> + transform(F &&f) const & { + return has_value() + ? expected, error_type>( + detail::invoke(std::forward(f))) + : make_unexpected(error()); + } + + template ::value + &&std::is_void>::value)> + nsel_constexpr expected transform(F &&f) const & { + return has_value() ? (detail::invoke(std::forward(f)), + expected()) + : make_unexpected(error()); + } + +#if !nsel_COMPILER_GNUC_VERSION || nsel_COMPILER_GNUC_VERSION >= 490 + template ::value && + !std::is_void>::value)> + nsel_constexpr14 expected, error_type> + transform(F &&f) && { + return has_value() + ? expected, error_type>( + detail::invoke(std::forward(f))) + : make_unexpected(error()); + } + + template ::value + &&std::is_void>::value)> + nsel_constexpr14 expected transform(F &&f) && { + return has_value() ? (detail::invoke(std::forward(f)), + expected()) + : make_unexpected(error()); + } + + template ::value && + !std::is_void>::value)> + nsel_constexpr expected, error_type> + transform(F &&f) const && { + return has_value() + ? expected, error_type>( + detail::invoke(std::forward(f))) + : make_unexpected(error()); + } + + template ::value + &&std::is_void>::value)> + nsel_constexpr expected transform(F &&f) const && { + return has_value() ? (detail::invoke(std::forward(f)), + expected()) + : make_unexpected(error()); + } +#endif + + template >::value)> + nsel_constexpr14 + expected> + transform_error(F &&f) & { + return has_value() + ? expected>() + : make_unexpected(detail::invoke(std::forward(f), error())); + } + + template >::value)> + nsel_constexpr + expected> + transform_error(F &&f) const & { + return has_value() + ? expected>() + : make_unexpected(detail::invoke(std::forward(f), error())); + } + +#if !nsel_COMPILER_GNUC_VERSION || nsel_COMPILER_GNUC_VERSION >= 490 + template >::value)> + nsel_constexpr14 + expected> + transform_error(F &&f) && { + return has_value() ? expected>() + : make_unexpected(detail::invoke(std::forward(f), + std::move(error()))); + } + + template >::value)> + nsel_constexpr + expected> + transform_error(F &&f) const && { + return has_value() ? expected>() + : make_unexpected(detail::invoke(std::forward(f), + std::move(error()))); + } +#endif +#endif // nsel_P2505R >= 3 + + // template constexpr 'see below' unwrap() const&; + // + // template 'see below' unwrap() &&; + + // factories + + // template< typename Ex, typename F> + // expected catch_exception(F&& f); + // + // template< typename F> + // expected map(F&& func) ; + // + // template< typename F> + // 'see below' bind(F&& func) ; + // + // template< typename F> + // expected catch_error(F&& f); + // + // template< typename F> + // 'see below' then(F&& func); + + private: + detail::storage_t::value, + std::is_move_constructible::value> + contained; + }; + + // x.x.4.6 expected<>: comparison operators + + template ::value && + !std::is_void::value)> + constexpr bool operator==(expected const &x, + expected const &y) { + return bool(x) != bool(y) ? false + : bool(x) ? *x == *y + : x.error() == y.error(); + } + + template ::value &&std::is_void::value)> + constexpr bool operator==(expected const &x, + expected const &y) { + return bool(x) != bool(y) + ? false + : bool(x) || static_cast(x.error() == y.error()); + } + + template + constexpr bool operator!=(expected const &x, + expected const &y) { + return !(x == y); + } + +#if nsel_P0323R <= 2 + + template + constexpr bool operator<(expected const &x, expected const &y) { + return (!y) ? false : (!x) ? true : *x < *y; + } + + template + constexpr bool operator>(expected const &x, expected const &y) { + return (y < x); + } + + template + constexpr bool operator<=(expected const &x, expected const &y) { + return !(y < x); + } + + template + constexpr bool operator>=(expected const &x, expected const &y) { + return !(x < y); + } + +#endif + + // x.x.4.7 expected: comparison with T + + template ::value)> + constexpr bool operator==(expected const &x, T2 const &v) { + return bool(x) ? *x == v : false; + } + + template ::value)> + constexpr bool operator==(T2 const &v, expected const &x) { + return bool(x) ? v == *x : false; + } + + template + constexpr bool operator!=(expected const &x, T2 const &v) { + return bool(x) ? *x != v : true; + } + + template + constexpr bool operator!=(T2 const &v, expected const &x) { + return bool(x) ? v != *x : true; + } + +#if nsel_P0323R <= 2 + + template + constexpr bool operator<(expected const &x, T const &v) { + return bool(x) ? *x < v : true; + } + + template + constexpr bool operator<(T const &v, expected const &x) { + return bool(x) ? v < *x : false; + } + + template + constexpr bool operator>(T const &v, expected const &x) { + return bool(x) ? *x < v : false; + } + + template + constexpr bool operator>(expected const &x, T const &v) { + return bool(x) ? v < *x : false; + } + + template + constexpr bool operator<=(T const &v, expected const &x) { + return bool(x) ? !(*x < v) : false; + } + + template + constexpr bool operator<=(expected const &x, T const &v) { + return bool(x) ? !(v < *x) : true; + } + + template + constexpr bool operator>=(expected const &x, T const &v) { + return bool(x) ? !(*x < v) : false; + } + + template + constexpr bool operator>=(T const &v, expected const &x) { + return bool(x) ? !(v < *x) : true; + } + +#endif // nsel_P0323R + + // x.x.4.8 expected: comparison with unexpected_type + + template + constexpr bool operator==(expected const &x, + unexpected_type const &u) { + return (!x) ? x.get_unexpected() == u : false; + } + + template + constexpr bool operator==(unexpected_type const &u, + expected const &x) { + return (x == u); + } + + template + constexpr bool operator!=(expected const &x, + unexpected_type const &u) { + return !(x == u); + } + + template + constexpr bool operator!=(unexpected_type const &u, + expected const &x) { + return !(x == u); + } + +#if nsel_P0323R <= 2 + + template + constexpr bool operator<(expected const &x, + unexpected_type const &u) { + return (!x) ? (x.get_unexpected() < u) : false; + } + + template + constexpr bool operator<(unexpected_type const &u, + expected const &x) { + return (!x) ? (u < x.get_unexpected()) : true; + } + + template + constexpr bool operator>(expected const &x, + unexpected_type const &u) { + return (u < x); + } + + template + constexpr bool operator>(unexpected_type const &u, + expected const &x) { + return (x < u); + } + + template + constexpr bool operator<=(expected const &x, + unexpected_type const &u) { + return !(u < x); + } + + template + constexpr bool operator<=(unexpected_type const &u, + expected const &x) { + return !(x < u); + } + + template + constexpr bool operator>=(expected const &x, + unexpected_type const &u) { + return !(u > x); + } + + template + constexpr bool operator>=(unexpected_type const &u, + expected const &x) { + return !(x > u); + } + +#endif // nsel_P0323R + + /// x.x.x Specialized algorithms + + template ::value || + std::is_move_constructible::value) && + std::is_move_constructible::value && + std17::is_swappable::value && + std17::is_swappable::value)> + void swap(expected &x, + expected &y) noexcept(noexcept(x.swap(y))) { + x.swap(y); + } + +#if nsel_P0323R <= 3 + + template + constexpr auto + make_expected(T &&v) -> expected::type> { + return expected::type>(std::forward(v)); + } + + // expected specialization: + + auto inline make_expected() -> expected { + return expected(in_place); + } + + template + constexpr auto make_expected_from_current_exception() -> expected { + return expected(make_unexpected_from_current_exception()); + } + + template + auto make_expected_from_exception(std::exception_ptr v) -> expected { + return expected(unexpected_type( + std::forward(v))); + } + + template + constexpr auto + make_expected_from_error(E e) -> expected::type> { + return expected::type>(make_unexpected(e)); + } + + template ::type, void>::value)> + /*nsel_constexpr14*/ + auto + make_expected_from_call(F f) -> expected::type> { + try { + return make_expected(f()); + } catch (...) { + return make_unexpected_from_current_exception(); + } + } + + template ::type, void>::value)> + /*nsel_constexpr14*/ + auto make_expected_from_call(F f) -> expected { + try { + f(); + return make_expected(); + } catch (...) { + return make_unexpected_from_current_exception(); + } + } + +#endif // nsel_P0323R + + } // namespace expected_lite + + using namespace expected_lite; + + // using expected_lite::expected; + // using ... + +} // namespace nonstd + +namespace std { + +// expected: hash support + +template struct hash> { + using result_type = std::size_t; + using argument_type = nonstd::expected; + + constexpr result_type operator()(argument_type const &arg) const { + return arg ? std::hash{}(*arg) : result_type{}; + } }; -// expected_delete_ctor_base will conditionally delete copy and move -// constructors depending on whether T is copy/move constructible -template::value && std::is_copy_constructible::value), - bool EnableMove = (is_move_constructible_or_void::value && std::is_move_constructible::value)> -struct expected_delete_ctor_base { - expected_delete_ctor_base() = default; - expected_delete_ctor_base(const expected_delete_ctor_base &) = default; - expected_delete_ctor_base(expected_delete_ctor_base &&) noexcept = default; - expected_delete_ctor_base &operator=(const expected_delete_ctor_base &) = default; - expected_delete_ctor_base &operator=(expected_delete_ctor_base &&) noexcept = default; +// TBD - ?? remove? see spec. +template struct hash> { + using result_type = std::size_t; + using argument_type = nonstd::expected; + + constexpr result_type operator()(argument_type const &arg) const { + return arg ? std::hash{}(*arg) : result_type{}; + } }; -template -struct expected_delete_ctor_base { - expected_delete_ctor_base() = default; - expected_delete_ctor_base(const expected_delete_ctor_base &) = default; - expected_delete_ctor_base(expected_delete_ctor_base &&) noexcept = delete; - expected_delete_ctor_base &operator=(const expected_delete_ctor_base &) = default; - expected_delete_ctor_base &operator=(expected_delete_ctor_base &&) noexcept = default; -}; +// TBD - implement +// bool(e), hash>()(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.error()). -template -struct expected_delete_ctor_base { - expected_delete_ctor_base() = default; - expected_delete_ctor_base(const expected_delete_ctor_base &) = delete; - expected_delete_ctor_base(expected_delete_ctor_base &&) noexcept = default; - expected_delete_ctor_base &operator=(const expected_delete_ctor_base &) = default; - expected_delete_ctor_base &operator=(expected_delete_ctor_base &&) noexcept = default; -}; +template struct hash> {}; -template -struct expected_delete_ctor_base { - expected_delete_ctor_base() = default; - expected_delete_ctor_base(const expected_delete_ctor_base &) = delete; - expected_delete_ctor_base(expected_delete_ctor_base &&) noexcept = delete; - expected_delete_ctor_base &operator=(const expected_delete_ctor_base &) = default; - expected_delete_ctor_base &operator=(expected_delete_ctor_base &&) noexcept = default; -}; +} // namespace std -// expected_delete_assign_base will conditionally delete copy and move -// constructors depending on whether T and E are copy/move constructible + -// assignable -template::value && std::is_copy_constructible::value - && is_copy_assignable_or_void::value && std::is_copy_assignable::value), - bool EnableMove = (is_move_constructible_or_void::value && std::is_move_constructible::value - && is_move_assignable_or_void::value && std::is_move_assignable::value)> -struct expected_delete_assign_base { - expected_delete_assign_base() = default; - expected_delete_assign_base(const expected_delete_assign_base &) = default; - expected_delete_assign_base(expected_delete_assign_base &&) noexcept = default; - expected_delete_assign_base &operator=(const expected_delete_assign_base &) = default; - expected_delete_assign_base &operator=(expected_delete_assign_base &&) noexcept = default; -}; +namespace nonstd { -template -struct expected_delete_assign_base { - expected_delete_assign_base() = default; - expected_delete_assign_base(const expected_delete_assign_base &) = default; - expected_delete_assign_base(expected_delete_assign_base &&) noexcept = default; - expected_delete_assign_base &operator=(const expected_delete_assign_base &) = default; - expected_delete_assign_base &operator=(expected_delete_assign_base &&) noexcept = delete; -}; +// void unexpected() is deprecated && removed in C++17 -template -struct expected_delete_assign_base { - expected_delete_assign_base() = default; - expected_delete_assign_base(const expected_delete_assign_base &) = default; - expected_delete_assign_base(expected_delete_assign_base &&) noexcept = default; - expected_delete_assign_base &operator=(const expected_delete_assign_base &) = delete; - expected_delete_assign_base &operator=(expected_delete_assign_base &&) noexcept = default; -}; - -template -struct expected_delete_assign_base { - expected_delete_assign_base() = default; - expected_delete_assign_base(const expected_delete_assign_base &) = default; - expected_delete_assign_base(expected_delete_assign_base &&) noexcept = default; - expected_delete_assign_base &operator=(const expected_delete_assign_base &) = delete; - expected_delete_assign_base &operator=(expected_delete_assign_base &&) noexcept = delete; -}; - -// This is needed to be able to construct the expected_default_ctor_base which -// follows, while still conditionally deleting the default constructor. -struct default_constructor_tag { - explicit constexpr default_constructor_tag() = default; -}; - -// expected_default_ctor_base will ensure that expected has a deleted default -// consturctor if T is not default constructible. -// This specialization is for when T is default constructible -template::value || std::is_void::value> -struct expected_default_ctor_base { - constexpr expected_default_ctor_base() noexcept = default; - constexpr expected_default_ctor_base(expected_default_ctor_base const &) noexcept = default; - constexpr expected_default_ctor_base(expected_default_ctor_base &&) noexcept = default; - expected_default_ctor_base &operator=(expected_default_ctor_base const &) noexcept = default; - expected_default_ctor_base &operator=(expected_default_ctor_base &&) noexcept = default; - - constexpr explicit expected_default_ctor_base(default_constructor_tag) {} -}; - -// This specialization is for when T is not default constructible -template -struct expected_default_ctor_base { - constexpr expected_default_ctor_base() noexcept = delete; - constexpr expected_default_ctor_base(expected_default_ctor_base const &) noexcept = default; - constexpr expected_default_ctor_base(expected_default_ctor_base &&) noexcept = default; - expected_default_ctor_base &operator=(expected_default_ctor_base const &) noexcept = default; - expected_default_ctor_base &operator=(expected_default_ctor_base &&) noexcept = default; - - constexpr explicit expected_default_ctor_base(default_constructor_tag) {} -}; -}// namespace detail - -template -class bad_expected_access : public std::exception { -public: - explicit bad_expected_access(E e) : m_val(std::move(e)) {} - - virtual const char *what() const noexcept override { return "Bad expected access"; } - - const E &error() const & { return m_val; } - - E &error() & { return m_val; } - - const E &&error() const && { return std::move(m_val); } - - E &&error() && { return std::move(m_val); } - -private: - E m_val; -}; - -/// An `expected` object is an object that contains the storage for -/// another object and manages the lifetime of this contained object `T`. -/// Alternatively it could contain the storage for another unexpected object -/// `E`. The contained object may not be initialized after the expected object -/// has been initialized, and may not be destroyed before the expected object -/// has been destroyed. The initialization state of the contained object is -/// tracked by the expected object. -template -class expected - : private detail::expected_move_assign_base, - private detail::expected_delete_ctor_base, - private detail::expected_delete_assign_base, - private detail::expected_default_ctor_base { - static_assert(!std::is_reference::value, "T must not be a reference"); - static_assert(!std::is_same::type>::value, "T must not be in_place_t"); - static_assert(!std::is_same::type>::value, "T must not be unexpect_t"); - static_assert(!std::is_same>::type>::value, "T must not be unexpected"); - static_assert(!std::is_reference::value, "E must not be a reference"); - - T *valptr() { return std::addressof(this->m_val); } - - const T *valptr() const { return std::addressof(this->m_val); } - - unexpected *errptr() { return std::addressof(this->m_unexpect); } - - const unexpected *errptr() const { return std::addressof(this->m_unexpect); } - - template::value> * = nullptr> - TL_EXPECTED_11_CONSTEXPR U &val() - { - return this->m_val; - } - - TL_EXPECTED_11_CONSTEXPR unexpected &err() { return this->m_unexpect; } - - template::value> * = nullptr> - constexpr const U &val() const - { - return this->m_val; - } - - constexpr const unexpected &err() const { return this->m_unexpect; } - - using impl_base = detail::expected_move_assign_base; - using ctor_base = detail::expected_default_ctor_base; - -public: - typedef T value_type; - typedef E error_type; - typedef unexpected unexpected_type; - -#if defined(TL_EXPECTED_CXX14) && !defined(TL_EXPECTED_GCC49) && !defined(TL_EXPECTED_GCC54) \ - && !defined(TL_EXPECTED_GCC55) - template - TL_EXPECTED_11_CONSTEXPR auto and_then(F &&f) & - { - return and_then_impl(*this, std::forward(f)); - } - - template - TL_EXPECTED_11_CONSTEXPR auto and_then(F &&f) && - { - return and_then_impl(std::move(*this), std::forward(f)); - } - - template - constexpr auto and_then(F &&f) const & - { - return and_then_impl(*this, std::forward(f)); - } - -#ifndef TL_EXPECTED_NO_CONSTRR - template - constexpr auto and_then(F &&f) const && - { - return and_then_impl(std::move(*this), std::forward(f)); - } +#if nsel_CPP17_OR_GREATER || nsel_COMPILER_MSVC_VERSION > 141 +template using unexpected = unexpected_type; #endif -#else - template - TL_EXPECTED_11_CONSTEXPR auto - and_then(F &&f) & -> decltype(and_then_impl(std::declval(), std::forward(f))) - { - return and_then_impl(*this, std::forward(f)); - } +} // namespace nonstd - template - TL_EXPECTED_11_CONSTEXPR auto - and_then(F &&f) && -> decltype(and_then_impl(std::declval(), std::forward(f))) - { - return and_then_impl(std::move(*this), std::forward(f)); - } +#undef nsel_REQUIRES +#undef nsel_REQUIRES_0 +#undef nsel_REQUIRES_T - template - constexpr auto - and_then(F &&f) const & -> decltype(and_then_impl(std::declval(), std::forward(f))) - { - return and_then_impl(*this, std::forward(f)); - } +nsel_RESTORE_WARNINGS() -#ifndef TL_EXPECTED_NO_CONSTRR - template - constexpr auto - and_then(F &&f) const && -> decltype(and_then_impl(std::declval(), std::forward(f))) - { - return and_then_impl(std::move(*this), std::forward(f)); - } -#endif -#endif - -#if defined(TL_EXPECTED_CXX14) && !defined(TL_EXPECTED_GCC49) && !defined(TL_EXPECTED_GCC54) \ - && !defined(TL_EXPECTED_GCC55) - template - TL_EXPECTED_11_CONSTEXPR auto map(F &&f) & - { - return expected_map_impl(*this, std::forward(f)); - } - - template - TL_EXPECTED_11_CONSTEXPR auto map(F &&f) && - { - return expected_map_impl(std::move(*this), std::forward(f)); - } - - template - constexpr auto map(F &&f) const & - { - return expected_map_impl(*this, std::forward(f)); - } - - template - constexpr auto map(F &&f) const && - { - return expected_map_impl(std::move(*this), std::forward(f)); - } -#else - template - TL_EXPECTED_11_CONSTEXPR decltype(expected_map_impl(std::declval(), std::declval())) map(F &&f) & - { - return expected_map_impl(*this, std::forward(f)); - } - - template - TL_EXPECTED_11_CONSTEXPR decltype(expected_map_impl(std::declval(), std::declval())) map(F &&f) && - { - return expected_map_impl(std::move(*this), std::forward(f)); - } - - template - constexpr decltype(expected_map_impl(std::declval(), std::declval())) map(F &&f) const & - { - return expected_map_impl(*this, std::forward(f)); - } - -#ifndef TL_EXPECTED_NO_CONSTRR - template - constexpr decltype(expected_map_impl(std::declval(), std::declval())) map(F &&f) const && - { - return expected_map_impl(std::move(*this), std::forward(f)); - } -#endif -#endif - -#if defined(TL_EXPECTED_CXX14) && !defined(TL_EXPECTED_GCC49) && !defined(TL_EXPECTED_GCC54) \ - && !defined(TL_EXPECTED_GCC55) - template - TL_EXPECTED_11_CONSTEXPR auto transform(F &&f) & - { - return expected_map_impl(*this, std::forward(f)); - } - - template - TL_EXPECTED_11_CONSTEXPR auto transform(F &&f) && - { - return expected_map_impl(std::move(*this), std::forward(f)); - } - - template - constexpr auto transform(F &&f) const & - { - return expected_map_impl(*this, std::forward(f)); - } - - template - constexpr auto transform(F &&f) const && - { - return expected_map_impl(std::move(*this), std::forward(f)); - } -#else - template - TL_EXPECTED_11_CONSTEXPR decltype(expected_map_impl(std::declval(), std::declval())) - transform(F &&f) & - { - return expected_map_impl(*this, std::forward(f)); - } - - template - TL_EXPECTED_11_CONSTEXPR decltype(expected_map_impl(std::declval(), std::declval())) - transform(F &&f) && - { - return expected_map_impl(std::move(*this), std::forward(f)); - } - - template - constexpr decltype(expected_map_impl(std::declval(), std::declval())) - transform(F &&f) const & - { - return expected_map_impl(*this, std::forward(f)); - } - -#ifndef TL_EXPECTED_NO_CONSTRR - template - constexpr decltype(expected_map_impl(std::declval(), std::declval())) - transform(F &&f) const && - { - return expected_map_impl(std::move(*this), std::forward(f)); - } -#endif -#endif - -#if defined(TL_EXPECTED_CXX14) && !defined(TL_EXPECTED_GCC49) && !defined(TL_EXPECTED_GCC54) \ - && !defined(TL_EXPECTED_GCC55) - template - TL_EXPECTED_11_CONSTEXPR auto map_error(F &&f) & - { - return map_error_impl(*this, std::forward(f)); - } - - template - TL_EXPECTED_11_CONSTEXPR auto map_error(F &&f) && - { - return map_error_impl(std::move(*this), std::forward(f)); - } - - template - constexpr auto map_error(F &&f) const & - { - return map_error_impl(*this, std::forward(f)); - } - - template - constexpr auto map_error(F &&f) const && - { - return map_error_impl(std::move(*this), std::forward(f)); - } -#else - template - TL_EXPECTED_11_CONSTEXPR decltype(map_error_impl(std::declval(), std::declval())) - map_error(F &&f) & - { - return map_error_impl(*this, std::forward(f)); - } - - template - TL_EXPECTED_11_CONSTEXPR decltype(map_error_impl(std::declval(), std::declval())) - map_error(F &&f) && - { - return map_error_impl(std::move(*this), std::forward(f)); - } - - template - constexpr decltype(map_error_impl(std::declval(), std::declval())) map_error(F &&f) const & - { - return map_error_impl(*this, std::forward(f)); - } - -#ifndef TL_EXPECTED_NO_CONSTRR - template - constexpr decltype(map_error_impl(std::declval(), std::declval())) - map_error(F &&f) const && - { - return map_error_impl(std::move(*this), std::forward(f)); - } -#endif -#endif -#if defined(TL_EXPECTED_CXX14) && !defined(TL_EXPECTED_GCC49) && !defined(TL_EXPECTED_GCC54) \ - && !defined(TL_EXPECTED_GCC55) - template - TL_EXPECTED_11_CONSTEXPR auto transform_error(F &&f) & - { - return map_error_impl(*this, std::forward(f)); - } - - template - TL_EXPECTED_11_CONSTEXPR auto transform_error(F &&f) && - { - return map_error_impl(std::move(*this), std::forward(f)); - } - - template - constexpr auto transform_error(F &&f) const & - { - return map_error_impl(*this, std::forward(f)); - } - - template - constexpr auto transform_error(F &&f) const && - { - return map_error_impl(std::move(*this), std::forward(f)); - } -#else - template - TL_EXPECTED_11_CONSTEXPR decltype(map_error_impl(std::declval(), std::declval())) - transform_error(F &&f) & - { - return map_error_impl(*this, std::forward(f)); - } - - template - TL_EXPECTED_11_CONSTEXPR decltype(map_error_impl(std::declval(), std::declval())) - transform_error(F &&f) && - { - return map_error_impl(std::move(*this), std::forward(f)); - } - - template - constexpr decltype(map_error_impl(std::declval(), std::declval())) - transform_error(F &&f) const & - { - return map_error_impl(*this, std::forward(f)); - } - -#ifndef TL_EXPECTED_NO_CONSTRR - template - constexpr decltype(map_error_impl(std::declval(), std::declval())) - transform_error(F &&f) const && - { - return map_error_impl(std::move(*this), std::forward(f)); - } -#endif -#endif - template - expected TL_EXPECTED_11_CONSTEXPR or_else(F &&f) & - { - return or_else_impl(*this, std::forward(f)); - } - - template - expected TL_EXPECTED_11_CONSTEXPR or_else(F &&f) && - { - return or_else_impl(std::move(*this), std::forward(f)); - } - - template - expected constexpr or_else(F &&f) const & - { - return or_else_impl(*this, std::forward(f)); - } - -#ifndef TL_EXPECTED_NO_CONSTRR - template - expected constexpr or_else(F &&f) const && - { - return or_else_impl(std::move(*this), std::forward(f)); - } -#endif - constexpr expected() = default; - constexpr expected(const expected &rhs) = default; - constexpr expected(expected &&rhs) = default; - expected &operator=(const expected &rhs) = default; - expected &operator=(expected &&rhs) = default; - - template::value> * = nullptr> - constexpr expected(in_place_t, Args &&...args) - : impl_base(in_place, std::forward(args)...), - ctor_base(detail::default_constructor_tag{}) - {} - - template &, Args &&...>::value> * = nullptr> - constexpr expected(in_place_t, std::initializer_list il, Args &&...args) - : impl_base(in_place, il, std::forward(args)...), - ctor_base(detail::default_constructor_tag{}) - {} - - template::value> * = nullptr, - detail::enable_if_t::value> * = nullptr> - explicit constexpr expected(const unexpected &e) - : impl_base(unexpect, e.value()), - ctor_base(detail::default_constructor_tag{}) - {} - - template::value> * = nullptr, - detail::enable_if_t::value> * = nullptr> - constexpr expected(unexpected const &e) - : impl_base(unexpect, e.value()), - ctor_base(detail::default_constructor_tag{}) - {} - - template::value> * = nullptr, - detail::enable_if_t::value> * = nullptr> - explicit constexpr expected(unexpected &&e) noexcept(std::is_nothrow_constructible::value) - : impl_base(unexpect, std::move(e.value())), - ctor_base(detail::default_constructor_tag{}) - {} - - template::value> * = nullptr, - detail::enable_if_t::value> * = nullptr> - constexpr expected(unexpected &&e) noexcept(std::is_nothrow_constructible::value) - : impl_base(unexpect, std::move(e.value())), - ctor_base(detail::default_constructor_tag{}) - {} - - template::value> * = nullptr> - constexpr explicit expected(unexpect_t, Args &&...args) - : impl_base(unexpect, std::forward(args)...), - ctor_base(detail::default_constructor_tag{}) - {} - - template &, Args &&...>::value> * = nullptr> - constexpr explicit expected(unexpect_t, std::initializer_list il, Args &&...args) - : impl_base(unexpect, il, std::forward(args)...), - ctor_base(detail::default_constructor_tag{}) - {} - - template::value - && std::is_convertible::value)> * = nullptr, - detail::expected_enable_from_other * = nullptr> - explicit TL_EXPECTED_11_CONSTEXPR expected(const expected &rhs) : ctor_base(detail::default_constructor_tag{}) - { - if (rhs.has_value()) { - this->construct(*rhs); - } else { - this->construct_error(rhs.error()); - } - } - - template::value && std::is_convertible::value)> - * = nullptr, - detail::expected_enable_from_other * = nullptr> - TL_EXPECTED_11_CONSTEXPR expected(const expected &rhs) : ctor_base(detail::default_constructor_tag{}) - { - if (rhs.has_value()) { - this->construct(*rhs); - } else { - this->construct_error(rhs.error()); - } - } - - template< - class U, - class G, - detail::enable_if_t::value && std::is_convertible::value)> * = nullptr, - detail::expected_enable_from_other * = nullptr> - explicit TL_EXPECTED_11_CONSTEXPR expected(expected &&rhs) : ctor_base(detail::default_constructor_tag{}) - { - if (rhs.has_value()) { - this->construct(std::move(*rhs)); - } else { - this->construct_error(std::move(rhs.error())); - } - } - - template< - class U, - class G, - detail::enable_if_t<(std::is_convertible::value && std::is_convertible::value)> * = nullptr, - detail::expected_enable_from_other * = nullptr> - TL_EXPECTED_11_CONSTEXPR expected(expected &&rhs) : ctor_base(detail::default_constructor_tag{}) - { - if (rhs.has_value()) { - this->construct(std::move(*rhs)); - } else { - this->construct_error(std::move(rhs.error())); - } - } - - template::value> * = nullptr, - detail::expected_enable_forward_value * = nullptr> - explicit TL_EXPECTED_MSVC2015_CONSTEXPR expected(U &&v) : expected(in_place, std::forward(v)) - {} - - template::value> * = nullptr, - detail::expected_enable_forward_value * = nullptr> - TL_EXPECTED_MSVC2015_CONSTEXPR expected(U &&v) : expected(in_place, std::forward(v)) - {} - - template::value> * = nullptr, - detail::enable_if_t::value> * = nullptr, - detail::enable_if_t<(!std::is_same, detail::decay_t>::value - && !detail::conjunction, std::is_same>>::value - && std::is_constructible::value && std::is_assignable::value - && std::is_nothrow_move_constructible::value)> * = nullptr> - expected &operator=(U &&v) - { - if (has_value()) { - val() = std::forward(v); - } else { - err().~unexpected(); - ::new (valptr()) T(std::forward(v)); - this->m_has_val = true; - } - - return *this; - } - - template::value> * = nullptr, - detail::enable_if_t::value> * = nullptr, - detail::enable_if_t<(!std::is_same, detail::decay_t>::value - && !detail::conjunction, std::is_same>>::value - && std::is_constructible::value && std::is_assignable::value - && std::is_nothrow_move_constructible::value)> * = nullptr> - expected &operator=(U &&v) - { - if (has_value()) { - val() = std::forward(v); - } else { - auto tmp = std::move(err()); - err().~unexpected(); - -#ifdef TL_EXPECTED_EXCEPTIONS_ENABLED - try { - ::new (valptr()) T(std::forward(v)); - this->m_has_val = true; - } catch (...) { - err() = std::move(tmp); - throw; - } -#else - ::new (valptr()) T(std::forward(v)); - this->m_has_val = true; -#endif - } - - return *this; - } - - template::value && std::is_assignable::value> - * = nullptr> - expected &operator=(const unexpected &rhs) - { - if (!has_value()) { - err() = rhs; - } else { - this->destroy_val(); - ::new (errptr()) unexpected(rhs); - this->m_has_val = false; - } - - return *this; - } - - template::value && std::is_move_assignable::value> - * = nullptr> - expected &operator=(unexpected &&rhs) noexcept - { - if (!has_value()) { - err() = std::move(rhs); - } else { - this->destroy_val(); - ::new (errptr()) unexpected(std::move(rhs)); - this->m_has_val = false; - } - - return *this; - } - - template::value> * = nullptr> - void emplace(Args &&...args) - { - if (has_value()) { - val().~T(); - } else { - err().~unexpected(); - this->m_has_val = true; - } - ::new (valptr()) T(std::forward(args)...); - } - - template::value> * = nullptr> - void emplace(Args &&...args) - { - if (has_value()) { - val().~T(); - ::new (valptr()) T(std::forward(args)...); - } else { - auto tmp = std::move(err()); - err().~unexpected(); - -#ifdef TL_EXPECTED_EXCEPTIONS_ENABLED - try { - ::new (valptr()) T(std::forward(args)...); - this->m_has_val = true; - } catch (...) { - err() = std::move(tmp); - throw; - } -#else - ::new (valptr()) T(std::forward(args)...); - this->m_has_val = true; -#endif - } - } - - template &, Args &&...>::value> - * = nullptr> - void emplace(std::initializer_list il, Args &&...args) - { - if (has_value()) { - T t(il, std::forward(args)...); - val() = std::move(t); - } else { - err().~unexpected(); - ::new (valptr()) T(il, std::forward(args)...); - this->m_has_val = true; - } - } - - template &, Args &&...>::value> - * = nullptr> - void emplace(std::initializer_list il, Args &&...args) - { - if (has_value()) { - T t(il, std::forward(args)...); - val() = std::move(t); - } else { - auto tmp = std::move(err()); - err().~unexpected(); - -#ifdef TL_EXPECTED_EXCEPTIONS_ENABLED - try { - ::new (valptr()) T(il, std::forward(args)...); - this->m_has_val = true; - } catch (...) { - err() = std::move(tmp); - throw; - } -#else - ::new (valptr()) T(il, std::forward(args)...); - this->m_has_val = true; -#endif - } - } - -private: - using t_is_void = std::true_type; - using t_is_not_void = std::false_type; - using t_is_nothrow_move_constructible = std::true_type; - using move_constructing_t_can_throw = std::false_type; - using e_is_nothrow_move_constructible = std::true_type; - using move_constructing_e_can_throw = std::false_type; - - void swap_where_both_have_value(expected & /*rhs*/, t_is_void) noexcept - { - // swapping void is a no-op - } - - void swap_where_both_have_value(expected &rhs, t_is_not_void) - { - using std::swap; - swap(val(), rhs.val()); - } - - void swap_where_only_one_has_value(expected &rhs, t_is_void) noexcept(std::is_nothrow_move_constructible::value) - { - ::new (errptr()) unexpected_type(std::move(rhs.err())); - rhs.err().~unexpected_type(); - std::swap(this->m_has_val, rhs.m_has_val); - } - - void swap_where_only_one_has_value(expected &rhs, t_is_not_void) - { - swap_where_only_one_has_value_and_t_is_not_void( - rhs, - typename std::is_nothrow_move_constructible::type{}, - typename std::is_nothrow_move_constructible::type{}); - } - - void swap_where_only_one_has_value_and_t_is_not_void(expected &rhs, - t_is_nothrow_move_constructible, - e_is_nothrow_move_constructible) noexcept - { - auto temp = std::move(val()); - val().~T(); - ::new (errptr()) unexpected_type(std::move(rhs.err())); - rhs.err().~unexpected_type(); - ::new (rhs.valptr()) T(std::move(temp)); - std::swap(this->m_has_val, rhs.m_has_val); - } - - void swap_where_only_one_has_value_and_t_is_not_void(expected &rhs, - t_is_nothrow_move_constructible, - move_constructing_e_can_throw) - { - auto temp = std::move(val()); - val().~T(); -#ifdef TL_EXPECTED_EXCEPTIONS_ENABLED - try { - ::new (errptr()) unexpected_type(std::move(rhs.err())); - rhs.err().~unexpected_type(); - ::new (rhs.valptr()) T(std::move(temp)); - std::swap(this->m_has_val, rhs.m_has_val); - } catch (...) { - val() = std::move(temp); - throw; - } -#else - ::new (errptr()) unexpected_type(std::move(rhs.err())); - rhs.err().~unexpected_type(); - ::new (rhs.valptr()) T(std::move(temp)); - std::swap(this->m_has_val, rhs.m_has_val); -#endif - } - - void swap_where_only_one_has_value_and_t_is_not_void(expected &rhs, - move_constructing_t_can_throw, - e_is_nothrow_move_constructible) - { - auto temp = std::move(rhs.err()); - rhs.err().~unexpected_type(); -#ifdef TL_EXPECTED_EXCEPTIONS_ENABLED - try { - ::new (rhs.valptr()) T(std::move(val())); - val().~T(); - ::new (errptr()) unexpected_type(std::move(temp)); - std::swap(this->m_has_val, rhs.m_has_val); - } catch (...) { - rhs.err() = std::move(temp); - throw; - } -#else - ::new (rhs.valptr()) T(std::move(val())); - val().~T(); - ::new (errptr()) unexpected_type(std::move(temp)); - std::swap(this->m_has_val, rhs.m_has_val); -#endif - } - -public: - template - detail::enable_if_t::value && detail::is_swappable::value - && (std::is_nothrow_move_constructible::value - || std::is_nothrow_move_constructible::value)> - swap(expected &rhs) noexcept(std::is_nothrow_move_constructible::value && detail::is_nothrow_swappable::value - && std::is_nothrow_move_constructible::value - && detail::is_nothrow_swappable::value) - { - if (has_value() && rhs.has_value()) { - swap_where_both_have_value(rhs, typename std::is_void::type{}); - } else if (!has_value() && rhs.has_value()) { - rhs.swap(*this); - } else if (has_value()) { - swap_where_only_one_has_value(rhs, typename std::is_void::type{}); - } else { - using std::swap; - swap(err(), rhs.err()); - } - } - - constexpr const T *operator->() const - { - TL_ASSERT(has_value()); - return valptr(); - } - - TL_EXPECTED_11_CONSTEXPR T *operator->() - { - TL_ASSERT(has_value()); - return valptr(); - } - - template::value> * = nullptr> - constexpr const U &operator*() const & - { - TL_ASSERT(has_value()); - return val(); - } - - template::value> * = nullptr> - TL_EXPECTED_11_CONSTEXPR U &operator*() & - { - TL_ASSERT(has_value()); - return val(); - } - - template::value> * = nullptr> - constexpr const U &&operator*() const && - { - TL_ASSERT(has_value()); - return std::move(val()); - } - - template::value> * = nullptr> - TL_EXPECTED_11_CONSTEXPR U &&operator*() && - { - TL_ASSERT(has_value()); - return std::move(val()); - } - - constexpr bool has_value() const noexcept { return this->m_has_val; } - - constexpr explicit operator bool() const noexcept { return this->m_has_val; } - - template::value> * = nullptr> - TL_EXPECTED_11_CONSTEXPR const U &value() const & - { - if (!has_value()) detail::throw_exception(bad_expected_access(err().value())); - return val(); - } - - template::value> * = nullptr> - TL_EXPECTED_11_CONSTEXPR U &value() & - { - if (!has_value()) detail::throw_exception(bad_expected_access(err().value())); - return val(); - } - - template::value> * = nullptr> - TL_EXPECTED_11_CONSTEXPR const U &&value() const && - { - if (!has_value()) detail::throw_exception(bad_expected_access(std::move(err()).value())); - return std::move(val()); - } - - template::value> * = nullptr> - TL_EXPECTED_11_CONSTEXPR U &&value() && - { - if (!has_value()) detail::throw_exception(bad_expected_access(std::move(err()).value())); - return std::move(val()); - } - - constexpr const E &error() const & - { - TL_ASSERT(!has_value()); - return err().value(); - } - - TL_EXPECTED_11_CONSTEXPR E &error() & - { - TL_ASSERT(!has_value()); - return err().value(); - } - - constexpr const E &&error() const && - { - TL_ASSERT(!has_value()); - return std::move(err().value()); - } - - TL_EXPECTED_11_CONSTEXPR E &&error() && - { - TL_ASSERT(!has_value()); - return std::move(err().value()); - } - - template - constexpr T value_or(U &&v) const & - { - static_assert(std::is_copy_constructible::value && std::is_convertible::value, - "T must be copy-constructible and convertible to from U&&"); - return bool(*this) ? **this : static_cast(std::forward(v)); - } - - template - TL_EXPECTED_11_CONSTEXPR T value_or(U &&v) && - { - static_assert(std::is_move_constructible::value && std::is_convertible::value, - "T must be move-constructible and convertible to from U&&"); - return bool(*this) ? std::move(**this) : static_cast(std::forward(v)); - } -}; - -namespace detail { -template -using exp_t = typename detail::decay_t::value_type; -template -using err_t = typename detail::decay_t::error_type; -template -using ret_t = expected>; - -#ifdef TL_EXPECTED_CXX14 -template>::value> * = nullptr, - class Ret = decltype(detail::invoke(std::declval(), *std::declval()))> -constexpr auto -and_then_impl(Exp &&exp, F &&f) -{ - static_assert(detail::is_expected::value, "F must return an expected"); - - return exp.has_value() ? detail::invoke(std::forward(f), *std::forward(exp)) - : Ret(unexpect, std::forward(exp).error()); +#endif // nsel_USES_STD_EXPECTED +namespace std { +using namespace nonstd; } -template>::value> * = nullptr, - class Ret = decltype(detail::invoke(std::declval()))> -constexpr auto -and_then_impl(Exp &&exp, F &&f) -{ - static_assert(detail::is_expected::value, "F must return an expected"); - - return exp.has_value() ? detail::invoke(std::forward(f)) : Ret(unexpect, std::forward(exp).error()); -} -#else -template -struct TC; - -template(), *std::declval())), - detail::enable_if_t>::value> * = nullptr> -auto -and_then_impl(Exp &&exp, F &&f) -> Ret -{ - static_assert(detail::is_expected::value, "F must return an expected"); - - return exp.has_value() ? detail::invoke(std::forward(f), *std::forward(exp)) - : Ret(unexpect, std::forward(exp).error()); -} - -template())), - detail::enable_if_t>::value> * = nullptr> -constexpr auto -and_then_impl(Exp &&exp, F &&f) -> Ret -{ - static_assert(detail::is_expected::value, "F must return an expected"); - - return exp.has_value() ? detail::invoke(std::forward(f)) : Ret(unexpect, std::forward(exp).error()); -} -#endif - -#ifdef TL_EXPECTED_CXX14 -template>::value> * = nullptr, - class Ret = decltype(detail::invoke(std::declval(), *std::declval())), - detail::enable_if_t::value> * = nullptr> -constexpr auto -expected_map_impl(Exp &&exp, F &&f) -{ - using result = ret_t>; - return exp.has_value() ? result(detail::invoke(std::forward(f), *std::forward(exp))) - : result(unexpect, std::forward(exp).error()); -} - -template>::value> * = nullptr, - class Ret = decltype(detail::invoke(std::declval(), *std::declval())), - detail::enable_if_t::value> * = nullptr> -auto -expected_map_impl(Exp &&exp, F &&f) -{ - using result = expected>; - if (exp.has_value()) { - detail::invoke(std::forward(f), *std::forward(exp)); - return result(); - } - - return result(unexpect, std::forward(exp).error()); -} - -template>::value> * = nullptr, - class Ret = decltype(detail::invoke(std::declval())), - detail::enable_if_t::value> * = nullptr> -constexpr auto -expected_map_impl(Exp &&exp, F &&f) -{ - using result = ret_t>; - return exp.has_value() ? result(detail::invoke(std::forward(f))) - : result(unexpect, std::forward(exp).error()); -} - -template>::value> * = nullptr, - class Ret = decltype(detail::invoke(std::declval())), - detail::enable_if_t::value> * = nullptr> -auto -expected_map_impl(Exp &&exp, F &&f) -{ - using result = expected>; - if (exp.has_value()) { - detail::invoke(std::forward(f)); - return result(); - } - - return result(unexpect, std::forward(exp).error()); -} -#else -template>::value> * = nullptr, - class Ret = decltype(detail::invoke(std::declval(), *std::declval())), - detail::enable_if_t::value> * = nullptr> - -constexpr auto -expected_map_impl(Exp &&exp, F &&f) -> ret_t> -{ - using result = ret_t>; - - return exp.has_value() ? result(detail::invoke(std::forward(f), *std::forward(exp))) - : result(unexpect, std::forward(exp).error()); -} - -template>::value> * = nullptr, - class Ret = decltype(detail::invoke(std::declval(), *std::declval())), - detail::enable_if_t::value> * = nullptr> - -auto -expected_map_impl(Exp &&exp, F &&f) -> expected> -{ - if (exp.has_value()) { - detail::invoke(std::forward(f), *std::forward(exp)); - return {}; - } - - return unexpected>(std::forward(exp).error()); -} - -template>::value> * = nullptr, - class Ret = decltype(detail::invoke(std::declval())), - detail::enable_if_t::value> * = nullptr> - -constexpr auto -expected_map_impl(Exp &&exp, F &&f) -> ret_t> -{ - using result = ret_t>; - - return exp.has_value() ? result(detail::invoke(std::forward(f))) - : result(unexpect, std::forward(exp).error()); -} - -template>::value> * = nullptr, - class Ret = decltype(detail::invoke(std::declval())), - detail::enable_if_t::value> * = nullptr> - -auto -expected_map_impl(Exp &&exp, F &&f) -> expected> -{ - if (exp.has_value()) { - detail::invoke(std::forward(f)); - return {}; - } - - return unexpected>(std::forward(exp).error()); -} -#endif - -#if defined(TL_EXPECTED_CXX14) && !defined(TL_EXPECTED_GCC49) && !defined(TL_EXPECTED_GCC54) \ - && !defined(TL_EXPECTED_GCC55) -template>::value> * = nullptr, - class Ret = decltype(detail::invoke(std::declval(), std::declval().error())), - detail::enable_if_t::value> * = nullptr> -constexpr auto -map_error_impl(Exp &&exp, F &&f) -{ - using result = expected, detail::decay_t>; - return exp.has_value() ? result(*std::forward(exp)) - : result(unexpect, detail::invoke(std::forward(f), std::forward(exp).error())); -} - -template>::value> * = nullptr, - class Ret = decltype(detail::invoke(std::declval(), std::declval().error())), - detail::enable_if_t::value> * = nullptr> -auto -map_error_impl(Exp &&exp, F &&f) -{ - using result = expected, monostate>; - if (exp.has_value()) { return result(*std::forward(exp)); } - - detail::invoke(std::forward(f), std::forward(exp).error()); - return result(unexpect, monostate{}); -} - -template>::value> * = nullptr, - class Ret = decltype(detail::invoke(std::declval(), std::declval().error())), - detail::enable_if_t::value> * = nullptr> -constexpr auto -map_error_impl(Exp &&exp, F &&f) -{ - using result = expected, detail::decay_t>; - return exp.has_value() ? result() - : result(unexpect, detail::invoke(std::forward(f), std::forward(exp).error())); -} - -template>::value> * = nullptr, - class Ret = decltype(detail::invoke(std::declval(), std::declval().error())), - detail::enable_if_t::value> * = nullptr> -auto -map_error_impl(Exp &&exp, F &&f) -{ - using result = expected, monostate>; - if (exp.has_value()) { return result(); } - - detail::invoke(std::forward(f), std::forward(exp).error()); - return result(unexpect, monostate{}); -} -#else -template>::value> * = nullptr, - class Ret = decltype(detail::invoke(std::declval(), std::declval().error())), - detail::enable_if_t::value> * = nullptr> -constexpr auto -map_error_impl(Exp &&exp, F &&f) -> expected, detail::decay_t> -{ - using result = expected, detail::decay_t>; - - return exp.has_value() ? result(*std::forward(exp)) - : result(unexpect, detail::invoke(std::forward(f), std::forward(exp).error())); -} - -template>::value> * = nullptr, - class Ret = decltype(detail::invoke(std::declval(), std::declval().error())), - detail::enable_if_t::value> * = nullptr> -auto -map_error_impl(Exp &&exp, F &&f) -> expected, monostate> -{ - using result = expected, monostate>; - if (exp.has_value()) { return result(*std::forward(exp)); } - - detail::invoke(std::forward(f), std::forward(exp).error()); - return result(unexpect, monostate{}); -} - -template>::value> * = nullptr, - class Ret = decltype(detail::invoke(std::declval(), std::declval().error())), - detail::enable_if_t::value> * = nullptr> -constexpr auto -map_error_impl(Exp &&exp, F &&f) -> expected, detail::decay_t> -{ - using result = expected, detail::decay_t>; - - return exp.has_value() ? result() - : result(unexpect, detail::invoke(std::forward(f), std::forward(exp).error())); -} - -template>::value> * = nullptr, - class Ret = decltype(detail::invoke(std::declval(), std::declval().error())), - detail::enable_if_t::value> * = nullptr> -auto -map_error_impl(Exp &&exp, F &&f) -> expected, monostate> -{ - using result = expected, monostate>; - if (exp.has_value()) { return result(); } - - detail::invoke(std::forward(f), std::forward(exp).error()); - return result(unexpect, monostate{}); -} -#endif - -#ifdef TL_EXPECTED_CXX14 -template(), std::declval().error())), - detail::enable_if_t::value> * = nullptr> -constexpr auto -or_else_impl(Exp &&exp, F &&f) -{ - static_assert(detail::is_expected::value, "F must return an expected"); - return exp.has_value() ? std::forward(exp) - : detail::invoke(std::forward(f), std::forward(exp).error()); -} - -template(), std::declval().error())), - detail::enable_if_t::value> * = nullptr> -detail::decay_t -or_else_impl(Exp &&exp, F &&f) -{ - return exp.has_value() - ? std::forward(exp) - : (detail::invoke(std::forward(f), std::forward(exp).error()), std::forward(exp)); -} -#else -template(), std::declval().error())), - detail::enable_if_t::value> * = nullptr> -auto -or_else_impl(Exp &&exp, F &&f) -> Ret -{ - static_assert(detail::is_expected::value, "F must return an expected"); - return exp.has_value() ? std::forward(exp) - : detail::invoke(std::forward(f), std::forward(exp).error()); -} - -template(), std::declval().error())), - detail::enable_if_t::value> * = nullptr> -detail::decay_t -or_else_impl(Exp &&exp, F &&f) -{ - return exp.has_value() - ? std::forward(exp) - : (detail::invoke(std::forward(f), std::forward(exp).error()), std::forward(exp)); -} -#endif -}// namespace detail - -template -constexpr bool -operator==(const expected &lhs, const expected &rhs) -{ - return (lhs.has_value() != rhs.has_value()) ? false - : (!lhs.has_value() ? lhs.error() == rhs.error() : *lhs == *rhs); -} - -template -constexpr bool -operator!=(const expected &lhs, const expected &rhs) -{ - return (lhs.has_value() != rhs.has_value()) ? true : (!lhs.has_value() ? lhs.error() != rhs.error() : *lhs != *rhs); -} - -template -constexpr bool -operator==(const expected &lhs, const expected &rhs) -{ - return (lhs.has_value() != rhs.has_value()) ? false : (!lhs.has_value() ? lhs.error() == rhs.error() : true); -} - -template -constexpr bool -operator!=(const expected &lhs, const expected &rhs) -{ - return (lhs.has_value() != rhs.has_value()) ? true : (!lhs.has_value() ? lhs.error() == rhs.error() : false); -} - -template -constexpr bool -operator==(const expected &x, const U &v) -{ - return x.has_value() ? *x == v : false; -} - -template -constexpr bool -operator==(const U &v, const expected &x) -{ - return x.has_value() ? *x == v : false; -} - -template -constexpr bool -operator!=(const expected &x, const U &v) -{ - return x.has_value() ? *x != v : true; -} - -template -constexpr bool -operator!=(const U &v, const expected &x) -{ - return x.has_value() ? *x != v : true; -} - -template -constexpr bool -operator==(const expected &x, const unexpected &e) -{ - return x.has_value() ? false : x.error() == e.value(); -} - -template -constexpr bool -operator==(const unexpected &e, const expected &x) -{ - return x.has_value() ? false : x.error() == e.value(); -} - -template -constexpr bool -operator!=(const expected &x, const unexpected &e) -{ - return x.has_value() ? true : x.error() != e.value(); -} - -template -constexpr bool -operator!=(const unexpected &e, const expected &x) -{ - return x.has_value() ? true : x.error() != e.value(); -} - -template::value || std::is_move_constructible::value) - && detail::is_swappable::value && std::is_move_constructible::value - && detail::is_swappable::value> * = nullptr> -void -swap(expected &lhs, expected &rhs) noexcept(noexcept(lhs.swap(rhs))) -{ - lhs.swap(rhs); -} -}// namespace tl - -namespace sled { -using namespace tl; -} - -#endif +#endif // NONSTD_EXPECTED_LITE_HPP diff --git a/src/sled/operations_chain.h b/src/sled/operations_chain.h index 7a80e6d..3db7029 100644 --- a/src/sled/operations_chain.h +++ b/src/sled/operations_chain.h @@ -38,7 +38,7 @@ public: void Run() override { - has_run_ = true; + has_run_ = true; auto functor = std::move(functor_); functor(std::move(callback_)); } @@ -54,7 +54,7 @@ class OperationsChain final : public RefCountedNonVirtual { public: static scoped_refptr Create(); ~OperationsChain(); - OperationsChain(const OperationsChain &) = delete; + OperationsChain(const OperationsChain &) = delete; OperationsChain operator=(const OperationsChain &) = delete; void SetOnChainEmptyCallback(std::function on_chain_empty_callback); @@ -79,7 +79,7 @@ private: explicit CallbackHandle(scoped_refptr operations_chain); ~CallbackHandle(); - CallbackHandle(const CallbackHandle &) = delete; + CallbackHandle(const CallbackHandle &) = delete; CallbackHandle &operator=(const CallbackHandle &) = delete; void OnOperationComplete(); @@ -93,7 +93,7 @@ private: void OnOperationComplete(); std::queue> chained_operations_; - sled::optional> on_chain_empty_callback_; + tl::optional> on_chain_empty_callback_; }; }// namespace sled diff --git a/src/sled/optional.h b/src/sled/optional.h index 1419fed..4e593fd 100644 --- a/src/sled/optional.h +++ b/src/sled/optional.h @@ -2178,6 +2178,12 @@ struct hash> { }; }// namespace std +#endif + +#ifndef SLED_OPTIONAL_H +#define SLED_OPTIONAL_H + +// TODO: Remove this namespace sled { using namespace tl; } diff --git a/src/sled/status_or.h b/src/sled/status_or.h index 207e314..e8256d0 100644 --- a/src/sled/status_or.h +++ b/src/sled/status_or.h @@ -143,7 +143,7 @@ private: } Status status_; - sled::optional value_; + tl::optional value_; }; template diff --git a/src/sled/system/hot_reloader.cc b/src/sled/system/hot_reloader.cc index 85f7528..c71eb52 100644 --- a/src/sled/system/hot_reloader.cc +++ b/src/sled/system/hot_reloader.cc @@ -66,9 +66,9 @@ public: return false; } - sled::optional Update(bool force_reload) + tl::optional Update(bool force_reload) { - if (cr_plugin_update(ctx_, force_reload) == 0) { return sled::nullopt; } + if (cr_plugin_update(ctx_, force_reload) == 0) { return tl::nullopt; } return detail::TranslateFailure(ctx_.failure); } @@ -97,7 +97,7 @@ HotReloader::Initialize() return impl_->Initialize(); } -sled::optional +tl::optional HotReloader::UpdateOrError(bool force_reload) { return impl_->Update(force_reload); diff --git a/src/sled/system/hot_reloader.h b/src/sled/system/hot_reloader.h index e3433e0..9ef2127 100644 --- a/src/sled/system/hot_reloader.h +++ b/src/sled/system/hot_reloader.h @@ -76,7 +76,7 @@ public: * @force_reload: 如果当前库已经加载,是否reload当前库 * @ status: 如果不为nullptr,返回当前加载状态 **/ - sled::optional UpdateOrError(bool force_reload = true); + tl::optional UpdateOrError(bool force_reload = true); // bool Rollback(); void set_userdata(void *data); diff --git a/src/sled/variant.h b/src/sled/variant.h index bed846d..990a44c 100644 --- a/src/sled/variant.h +++ b/src/sled/variant.h @@ -5,9 +5,8 @@ // Distributed under the Boost Software License, Version 1.0. // (See accompanying file LICENSE.md or copy at http://boost.org/LICENSE_1_0.txt) -#pragma once -#ifndef SLED_MPARK_VARIANT_HPP -#define SLED_MPARK_VARIANT_HPP +#ifndef MPARK_VARIANT_HPP +#define MPARK_VARIANT_HPP /* variant synopsis @@ -242,8 +241,8 @@ namespace std { #define MPARK_ALWAYS_INLINE inline #endif -#if __has_builtin(__builtin_addressof) || (defined(__GNUC__) && __GNUC__ >= 7) \ - || defined(_MSC_VER) +#if __has_builtin(__builtin_addressof) || \ + (defined(__GNUC__) && __GNUC__ >= 7) || defined(_MSC_VER) #define MPARK_BUILTIN_ADDRESSOF #endif @@ -259,8 +258,8 @@ namespace std { #define MPARK_TYPE_PACK_ELEMENT #endif -#if defined(__cpp_constexpr) && __cpp_constexpr >= 200704 \ - && !(defined(__GNUC__) && __GNUC__ == 4 && __GNUC_MINOR__ == 9) +#if defined(__cpp_constexpr) && __cpp_constexpr >= 200704 && \ + !(defined(__GNUC__) && __GNUC__ == 4 && __GNUC_MINOR__ == 9) #define MPARK_CPP11_CONSTEXPR #endif @@ -268,8 +267,8 @@ namespace std { #define MPARK_CPP14_CONSTEXPR #endif -#if __has_feature(cxx_exceptions) || defined(__cpp_exceptions) \ - || (defined(_MSC_VER) && defined(_CPPUNWIND)) +#if __has_feature(cxx_exceptions) || defined(__cpp_exceptions) || \ + (defined(_MSC_VER) && defined(_CPPUNWIND)) #define MPARK_EXCEPTIONS #endif @@ -293,12 +292,12 @@ namespace std { #define MPARK_VARIABLE_TEMPLATES #endif -#if !defined(__GLIBCXX__) || __has_include()// >= libstdc++-5 +#if !defined(__GLIBCXX__) || __has_include() // >= libstdc++-5 #define MPARK_TRIVIALITY_TYPE_TRAITS #define MPARK_INCOMPLETE_TYPE_TRAITS #endif -#endif// MPARK_CONFIG_HPP +#endif // MPARK_CONFIG_HPP // MPark.Variant // @@ -312,35 +311,28 @@ namespace std { #include + namespace mpark { -struct in_place_t { - explicit in_place_t() = default; -}; + struct in_place_t { explicit in_place_t() = default; }; -template -struct in_place_index_t { - explicit in_place_index_t() = default; -}; + template + struct in_place_index_t { explicit in_place_index_t() = default; }; -template -struct in_place_type_t { - explicit in_place_type_t() = default; -}; + template + struct in_place_type_t { explicit in_place_type_t() = default; }; #ifdef MPARK_VARIABLE_TEMPLATES -constexpr in_place_t in_place{}; + constexpr in_place_t in_place{}; -template -constexpr in_place_index_t in_place_index{}; + template constexpr in_place_index_t in_place_index{}; -template -constexpr in_place_type_t in_place_type{}; + template constexpr in_place_type_t in_place_type{}; #endif -}// namespace mpark +} // namespace mpark -#endif// MPARK_IN_PLACE_HPP +#endif // MPARK_IN_PLACE_HPP // MPark.Variant // @@ -352,930 +344,883 @@ constexpr in_place_type_t in_place_type{}; #ifndef MPARK_LIB_HPP #define MPARK_LIB_HPP -#include #include +#include #include #include -#define MPARK_RETURN(...) \ - noexcept(noexcept(__VA_ARGS__))->decltype(__VA_ARGS__) \ - { \ - return __VA_ARGS__; \ - } + +#define MPARK_RETURN(...) \ + noexcept(noexcept(__VA_ARGS__)) -> decltype(__VA_ARGS__) { return __VA_ARGS__; } namespace mpark { -namespace lib { -template -struct identity { - using type = T; -}; + namespace lib { + template + struct identity { using type = T; }; -inline namespace cpp14 { -template -struct array { - constexpr const T &operator[](std::size_t index) const - { - return data[index]; - } + inline namespace cpp14 { + template + struct array { + constexpr const T &operator[](std::size_t index) const { + return data[index]; + } - T data[N == 0 ? 1 : N]; -}; + T data[N == 0 ? 1 : N]; + }; -template -using add_pointer_t = typename std::add_pointer::type; + template + using add_pointer_t = typename std::add_pointer::type; -template -using common_type_t = typename std::common_type::type; + template + using common_type_t = typename std::common_type::type; -template -using decay_t = typename std::decay::type; + template + using decay_t = typename std::decay::type; -template -using enable_if_t = typename std::enable_if::type; + template + using enable_if_t = typename std::enable_if::type; -template -using remove_const_t = typename std::remove_const::type; + template + using remove_const_t = typename std::remove_const::type; -template -using remove_reference_t = typename std::remove_reference::type; + template + using remove_reference_t = typename std::remove_reference::type; -template -inline constexpr T && -forward(remove_reference_t &t) noexcept -{ - return static_cast(t); -} + template + inline constexpr T &&forward(remove_reference_t &t) noexcept { + return static_cast(t); + } -template -inline constexpr T && -forward(remove_reference_t &&t) noexcept -{ - static_assert(!std::is_lvalue_reference::value, - "can not forward an rvalue as an lvalue"); - return static_cast(t); -} + template + inline constexpr T &&forward(remove_reference_t &&t) noexcept { + static_assert(!std::is_lvalue_reference::value, + "can not forward an rvalue as an lvalue"); + return static_cast(t); + } -template -inline constexpr remove_reference_t && -move(T &&t) noexcept -{ - return static_cast &&>(t); -} + template + inline constexpr remove_reference_t &&move(T &&t) noexcept { + return static_cast &&>(t); + } #ifdef MPARK_INTEGER_SEQUENCE -using std::index_sequence; -using std::index_sequence_for; -using std::integer_sequence; -using std::make_index_sequence; + using std::integer_sequence; + using std::index_sequence; + using std::make_index_sequence; + using std::index_sequence_for; #else -template -struct integer_sequence { - using value_type = T; + template + struct integer_sequence { + using value_type = T; + static constexpr std::size_t size() noexcept { return sizeof...(Is); } + }; - static constexpr std::size_t size() noexcept { return sizeof...(Is); } -}; + template + using index_sequence = integer_sequence; -template -using index_sequence = integer_sequence; + template + struct make_index_sequence_concat; -template -struct make_index_sequence_concat; + template + struct make_index_sequence_concat, + index_sequence> + : identity> {}; -template -struct make_index_sequence_concat, - index_sequence> - : identity> {}; + template + struct make_index_sequence_impl; -template -struct make_index_sequence_impl; + template + using make_index_sequence = typename make_index_sequence_impl::type; -template -using make_index_sequence = typename make_index_sequence_impl::type; + template + struct make_index_sequence_impl + : make_index_sequence_concat, + make_index_sequence> {}; -template -struct make_index_sequence_impl - : make_index_sequence_concat, - make_index_sequence> {}; + template <> + struct make_index_sequence_impl<0> : identity> {}; -template<> -struct make_index_sequence_impl<0> : identity> {}; + template <> + struct make_index_sequence_impl<1> : identity> {}; -template<> -struct make_index_sequence_impl<1> : identity> {}; - -template -using index_sequence_for = make_index_sequence; + template + using index_sequence_for = make_index_sequence; #endif -// + // #ifdef MPARK_TRANSPARENT_OPERATORS -using equal_to = std::equal_to<>; + using equal_to = std::equal_to<>; #else -struct equal_to { - template - inline constexpr auto operator()(Lhs &&lhs, Rhs &&rhs) const - MPARK_RETURN(lib::forward(lhs) == lib::forward(rhs)) -}; + struct equal_to { + template + inline constexpr auto operator()(Lhs &&lhs, Rhs &&rhs) const + MPARK_RETURN(lib::forward(lhs) == lib::forward(rhs)) + }; #endif #ifdef MPARK_TRANSPARENT_OPERATORS -using not_equal_to = std::not_equal_to<>; + using not_equal_to = std::not_equal_to<>; #else -struct not_equal_to { - template - inline constexpr auto operator()(Lhs &&lhs, Rhs &&rhs) const - MPARK_RETURN(lib::forward(lhs) != lib::forward(rhs)) -}; + struct not_equal_to { + template + inline constexpr auto operator()(Lhs &&lhs, Rhs &&rhs) const + MPARK_RETURN(lib::forward(lhs) != lib::forward(rhs)) + }; #endif #ifdef MPARK_TRANSPARENT_OPERATORS -using less = std::less<>; + using less = std::less<>; #else -struct less { - template - inline constexpr auto operator()(Lhs &&lhs, Rhs &&rhs) const - MPARK_RETURN(lib::forward(lhs) < lib::forward(rhs)) -}; + struct less { + template + inline constexpr auto operator()(Lhs &&lhs, Rhs &&rhs) const + MPARK_RETURN(lib::forward(lhs) < lib::forward(rhs)) + }; #endif #ifdef MPARK_TRANSPARENT_OPERATORS -using greater = std::greater<>; + using greater = std::greater<>; #else -struct greater { - template - inline constexpr auto operator()(Lhs &&lhs, Rhs &&rhs) const - MPARK_RETURN(lib::forward(lhs) > lib::forward(rhs)) -}; + struct greater { + template + inline constexpr auto operator()(Lhs &&lhs, Rhs &&rhs) const + MPARK_RETURN(lib::forward(lhs) > lib::forward(rhs)) + }; #endif #ifdef MPARK_TRANSPARENT_OPERATORS -using less_equal = std::less_equal<>; + using less_equal = std::less_equal<>; #else -struct less_equal { - template - inline constexpr auto operator()(Lhs &&lhs, Rhs &&rhs) const - MPARK_RETURN(lib::forward(lhs) <= lib::forward(rhs)) -}; + struct less_equal { + template + inline constexpr auto operator()(Lhs &&lhs, Rhs &&rhs) const + MPARK_RETURN(lib::forward(lhs) <= lib::forward(rhs)) + }; #endif #ifdef MPARK_TRANSPARENT_OPERATORS -using greater_equal = std::greater_equal<>; + using greater_equal = std::greater_equal<>; #else -struct greater_equal { - template - inline constexpr auto operator()(Lhs &&lhs, Rhs &&rhs) const - MPARK_RETURN(lib::forward(lhs) >= lib::forward(rhs)) -}; + struct greater_equal { + template + inline constexpr auto operator()(Lhs &&lhs, Rhs &&rhs) const + MPARK_RETURN(lib::forward(lhs) >= lib::forward(rhs)) + }; #endif -}// namespace cpp14 + } // namespace cpp14 -inline namespace cpp17 { + inline namespace cpp17 { -// -template -using bool_constant = std::integral_constant; + // + template + using bool_constant = std::integral_constant; -template -struct voider : identity {}; + template + struct voider : identity {}; -template -using void_t = typename voider::type; + template + using void_t = typename voider::type; -namespace detail { -namespace swappable { + namespace detail { + namespace swappable { -using std::swap; + using std::swap; -template -struct is_swappable { -private: - template(), - std::declval()))> - inline static std::true_type test(int); + template + struct is_swappable { + private: + template (), + std::declval()))> + inline static std::true_type test(int); - template - inline static std::false_type test(...); + template + inline static std::false_type test(...); -public: - static constexpr bool value = decltype(test(0))::value; -}; + public: + static constexpr bool value = decltype(test(0))::value; + }; -template -struct is_nothrow_swappable { - static constexpr bool value = - noexcept(swap(std::declval(), std::declval())); -}; + template + struct is_nothrow_swappable { + static constexpr bool value = + noexcept(swap(std::declval(), std::declval())); + }; -template -struct is_nothrow_swappable : std::false_type {}; + template + struct is_nothrow_swappable : std::false_type {}; -}// namespace swappable -}// namespace detail + } // namespace swappable + } // namespace detail -using detail::swappable::is_swappable; + using detail::swappable::is_swappable; -template -using is_nothrow_swappable = - detail::swappable::is_nothrow_swappable::value, T>; + template + using is_nothrow_swappable = + detail::swappable::is_nothrow_swappable::value, T>; -// -namespace detail { + // + namespace detail { -template -struct is_reference_wrapper : std::false_type {}; + template + struct is_reference_wrapper : std::false_type {}; -template -struct is_reference_wrapper> : std::true_type {}; + template + struct is_reference_wrapper> + : std::true_type {}; -template -struct Invoke; + template + struct Invoke; -template<> -struct Invoke { - template - inline static constexpr auto invoke(R T::*pmf, Arg &&arg, Args &&...args) - MPARK_RETURN((lib::forward(arg).*pmf)(lib::forward(args)...)) -}; + template <> + struct Invoke { + template + inline static constexpr auto invoke(R T::*pmf, Arg &&arg, Args &&... args) + MPARK_RETURN((lib::forward(arg).*pmf)(lib::forward(args)...)) + }; -template<> -struct Invoke { - template - inline static constexpr auto invoke(R T::*pmf, Arg &&arg, Args &&...args) - MPARK_RETURN((lib::forward(arg).get() - .*pmf)(lib::forward(args)...)) -}; + template <> + struct Invoke { + template + inline static constexpr auto invoke(R T::*pmf, Arg &&arg, Args &&... args) + MPARK_RETURN((lib::forward(arg).get().*pmf)(lib::forward(args)...)) + }; -template<> -struct Invoke { - template - inline static constexpr auto invoke(R T::*pmf, Arg &&arg, Args &&...args) - MPARK_RETURN(((*lib::forward(arg)) - .*pmf)(lib::forward(args)...)) -}; + template <> + struct Invoke { + template + inline static constexpr auto invoke(R T::*pmf, Arg &&arg, Args &&... args) + MPARK_RETURN(((*lib::forward(arg)).*pmf)(lib::forward(args)...)) + }; -template<> -struct Invoke { - template - inline static constexpr auto invoke(R T::*pmo, Arg &&arg) - MPARK_RETURN(lib::forward(arg).*pmo) -}; + template <> + struct Invoke { + template + inline static constexpr auto invoke(R T::*pmo, Arg &&arg) + MPARK_RETURN(lib::forward(arg).*pmo) + }; -template<> -struct Invoke { - template - inline static constexpr auto invoke(R T::*pmo, Arg &&arg) - MPARK_RETURN(lib::forward(arg).get().*pmo) -}; + template <> + struct Invoke { + template + inline static constexpr auto invoke(R T::*pmo, Arg &&arg) + MPARK_RETURN(lib::forward(arg).get().*pmo) + }; -template<> -struct Invoke { - template - inline static constexpr auto invoke(R T::*pmo, Arg &&arg) - MPARK_RETURN((*lib::forward(arg)).*pmo) -}; + template <> + struct Invoke { + template + inline static constexpr auto invoke(R T::*pmo, Arg &&arg) + MPARK_RETURN((*lib::forward(arg)).*pmo) + }; -template -inline constexpr auto -invoke(R T::*f, Arg &&arg, Args &&...args) - MPARK_RETURN(Invoke::value, - (std::is_base_of>::value ? 0 - : is_reference_wrapper>::value - ? 1 - : 2)>::invoke(f, - lib::forward(arg), - lib::forward(args)...)) + template + inline constexpr auto invoke(R T::*f, Arg &&arg, Args &&... args) + MPARK_RETURN( + Invoke::value, + (std::is_base_of>::value + ? 0 + : is_reference_wrapper>::value + ? 1 + : 2)>::invoke(f, + lib::forward(arg), + lib::forward(args)...)) #ifdef _MSC_VER #pragma warning(push) #pragma warning(disable : 4100) #endif - template - inline constexpr auto invoke(F &&f, Args &&...args) - MPARK_RETURN(lib::forward(f)(lib::forward(args)...)) + template + inline constexpr auto invoke(F &&f, Args &&... args) + MPARK_RETURN(lib::forward(f)(lib::forward(args)...)) #ifdef _MSC_VER #pragma warning(pop) #endif -}// namespace detail + } // namespace detail -template -inline constexpr auto -invoke(F &&f, Args &&...args) - MPARK_RETURN(detail::invoke(lib::forward(f), - lib::forward(args)...)) + template + inline constexpr auto invoke(F &&f, Args &&... args) + MPARK_RETURN(detail::invoke(lib::forward(f), + lib::forward(args)...)) - namespace detail -{ + namespace detail { - template - struct invoke_result {}; + template + struct invoke_result {}; - template - struct invoke_result(), - std::declval()...))>, - F, Args...> - : identity(), - std::declval()...))> {}; + template + struct invoke_result(), std::declval()...))>, + F, + Args...> + : identity(), std::declval()...))> {}; -}// namespace detail + } // namespace detail -template -using invoke_result = detail::invoke_result; + template + using invoke_result = detail::invoke_result; -template -using invoke_result_t = typename invoke_result::type; + template + using invoke_result_t = typename invoke_result::type; -namespace detail { + namespace detail { -template -struct is_invocable : std::false_type {}; + template + struct is_invocable : std::false_type {}; -template -struct is_invocable>, F, Args...> - : std::true_type {}; + template + struct is_invocable>, F, Args...> + : std::true_type {}; -template -struct is_invocable_r : std::false_type {}; + template + struct is_invocable_r : std::false_type {}; -template -struct is_invocable_r>, R, F, Args...> - : std::is_convertible, R> {}; + template + struct is_invocable_r>, + R, + F, + Args...> + : std::is_convertible, R> {}; -}// namespace detail + } // namespace detail -template -using is_invocable = detail::is_invocable; + template + using is_invocable = detail::is_invocable; -template -using is_invocable_r = detail::is_invocable_r; + template + using is_invocable_r = detail::is_invocable_r; -namespace detail { + namespace detail { -template -struct is_nothrow_invocable { - static constexpr bool value = - noexcept(lib::invoke(std::declval(), std::declval()...)); -}; + template + struct is_nothrow_invocable { + static constexpr bool value = + noexcept(lib::invoke(std::declval(), std::declval()...)); + }; -template -struct is_nothrow_invocable : std::false_type {}; + template + struct is_nothrow_invocable : std::false_type {}; -template -struct is_nothrow_invocable_r { -private: - inline static R impl() - { - return lib::invoke(std::declval(), std::declval()...); - } + template + struct is_nothrow_invocable_r { + private: + inline static R impl() { + return lib::invoke(std::declval(), std::declval()...); + } -public: - static constexpr bool value = noexcept(impl()); -}; + public: + static constexpr bool value = noexcept(impl()); + }; -template -struct is_nothrow_invocable_r : std::false_type {}; + template + struct is_nothrow_invocable_r : std::false_type {}; -}// namespace detail + } // namespace detail -template -using is_nothrow_invocable = - detail::is_nothrow_invocable::value, F, Args...>; + template + using is_nothrow_invocable = detail:: + is_nothrow_invocable::value, F, Args...>; -template -using is_nothrow_invocable_r = detail:: - is_nothrow_invocable_r::value, R, F, Args...>; + template + using is_nothrow_invocable_r = + detail::is_nothrow_invocable_r::value, + R, + F, + Args...>; -// + // #ifdef MPARK_BUILTIN_ADDRESSOF -template -inline constexpr T * -addressof(T &arg) noexcept -{ - return __builtin_addressof(arg); -} + template + inline constexpr T *addressof(T &arg) noexcept { + return __builtin_addressof(arg); + } #else -namespace detail { + namespace detail { -namespace has_addressof_impl { + namespace has_addressof_impl { -struct fail; + struct fail; -template -inline fail operator&(T &&); + template + inline fail operator&(T &&); -template -inline static constexpr bool -impl() -{ - return (std::is_class::value || std::is_union::value) - && !std::is_same()), fail>::value; -} + template + inline static constexpr bool impl() { + return (std::is_class::value || std::is_union::value) && + !std::is_same()), fail>::value; + } -}// namespace has_addressof_impl + } // namespace has_addressof_impl -template -using has_addressof = bool_constant()>; + template + using has_addressof = bool_constant()>; -template -inline constexpr T * -addressof(T &arg, std::true_type) noexcept -{ - return std::addressof(arg); -} + template + inline constexpr T *addressof(T &arg, std::true_type) noexcept { + return std::addressof(arg); + } -template -inline constexpr T * -addressof(T &arg, std::false_type) noexcept -{ - return &arg; -} + template + inline constexpr T *addressof(T &arg, std::false_type) noexcept { + return &arg; + } -}// namespace detail + } // namespace detail -template -inline constexpr T * -addressof(T &arg) noexcept -{ - return detail::addressof(arg, detail::has_addressof{}); -} + template + inline constexpr T *addressof(T &arg) noexcept { + return detail::addressof(arg, detail::has_addressof{}); + } #endif -template -inline constexpr T *addressof(const T &&) = delete; + template + inline constexpr T *addressof(const T &&) = delete; -}// namespace cpp17 + } // namespace cpp17 -template -struct remove_all_extents : identity {}; + template + struct remove_all_extents : identity {}; -template -struct remove_all_extents> : remove_all_extents {}; + template + struct remove_all_extents> : remove_all_extents {}; -template -using remove_all_extents_t = typename remove_all_extents::type; + template + using remove_all_extents_t = typename remove_all_extents::type; -template -using size_constant = std::integral_constant; + template + using size_constant = std::integral_constant; -template -struct indexed_type : size_constant { - using type = T; -}; + template + struct indexed_type : size_constant { using type = T; }; -template -using all = std::is_same, - integer_sequence>; + template + using all = std::is_same, + integer_sequence>; #ifdef MPARK_TYPE_PACK_ELEMENT -template -using type_pack_element_t = __type_pack_element; + template + using type_pack_element_t = __type_pack_element; #else -template -struct type_pack_element_impl { -private: - template - struct set; + template + struct type_pack_element_impl { + private: + template + struct set; - template - struct set> : indexed_type... {}; + template + struct set> : indexed_type... {}; - template - inline static std::enable_if impl(indexed_type); + template + inline static std::enable_if impl(indexed_type); - inline static std::enable_if impl(...); + inline static std::enable_if impl(...); -public: - using type = decltype(impl(set>{})); -}; + public: + using type = decltype(impl(set>{})); + }; -template -using type_pack_element = typename type_pack_element_impl::type; + template + using type_pack_element = typename type_pack_element_impl::type; -template -using type_pack_element_t = typename type_pack_element::type; + template + using type_pack_element_t = typename type_pack_element::type; #endif #ifdef MPARK_TRIVIALITY_TYPE_TRAITS -using std::is_trivially_copy_assignable; -using std::is_trivially_copy_constructible; -using std::is_trivially_move_assignable; -using std::is_trivially_move_constructible; + using std::is_trivially_copy_constructible; + using std::is_trivially_move_constructible; + using std::is_trivially_copy_assignable; + using std::is_trivially_move_assignable; #else -template -struct is_trivially_copy_constructible - : bool_constant::value &&__has_trivial_copy( - T)> {}; + template + struct is_trivially_copy_constructible + : bool_constant< + std::is_copy_constructible::value && __has_trivial_copy(T)> {}; -template -struct is_trivially_move_constructible : bool_constant<__is_trivial(T)> {}; + template + struct is_trivially_move_constructible : bool_constant<__is_trivial(T)> {}; -template -struct is_trivially_copy_assignable - : bool_constant::value &&__has_trivial_assign( - T)> {}; + template + struct is_trivially_copy_assignable + : bool_constant< + std::is_copy_assignable::value && __has_trivial_assign(T)> {}; -template -struct is_trivially_move_assignable : bool_constant<__is_trivial(T)> {}; + template + struct is_trivially_move_assignable : bool_constant<__is_trivial(T)> {}; #endif -template -struct dependent_type : T {}; + template + struct dependent_type : T {}; -template -struct push_back; + template + struct push_back; -template -using push_back_t = typename push_back::type; + template + using push_back_t = typename push_back::type; -template -struct push_back, J> { - using type = index_sequence; -}; + template + struct push_back, J> { + using type = index_sequence; + }; -}// namespace lib -}// namespace mpark + } // namespace lib +} // namespace mpark #undef MPARK_RETURN -#endif// MPARK_LIB_HPP +#endif // MPARK_LIB_HPP + namespace mpark { #ifdef MPARK_RETURN_TYPE_DEDUCTION #define AUTO auto -#define AUTO_RETURN(...) \ - { \ - return __VA_ARGS__; \ - } +#define AUTO_RETURN(...) { return __VA_ARGS__; } #define AUTO_REFREF auto && -#define AUTO_REFREF_RETURN(...) \ - { \ - return __VA_ARGS__; \ - } +#define AUTO_REFREF_RETURN(...) { return __VA_ARGS__; } #define DECLTYPE_AUTO decltype(auto) -#define DECLTYPE_AUTO_RETURN(...) \ - { \ - return __VA_ARGS__; \ - } +#define DECLTYPE_AUTO_RETURN(...) { return __VA_ARGS__; } #else #define AUTO auto -#define AUTO_RETURN(...) \ - ->lib::decay_t { return __VA_ARGS__; } +#define AUTO_RETURN(...) \ + -> lib::decay_t { return __VA_ARGS__; } #define AUTO_REFREF auto -#define AUTO_REFREF_RETURN(...) \ - ->decltype((__VA_ARGS__)) \ - { \ - static_assert(std::is_reference::value, ""); \ - return __VA_ARGS__; \ - } +#define AUTO_REFREF_RETURN(...) \ + -> decltype((__VA_ARGS__)) { \ + static_assert(std::is_reference::value, ""); \ + return __VA_ARGS__; \ + } #define DECLTYPE_AUTO auto -#define DECLTYPE_AUTO_RETURN(...) \ - ->decltype(__VA_ARGS__) { return __VA_ARGS__; } +#define DECLTYPE_AUTO_RETURN(...) \ + -> decltype(__VA_ARGS__) { return __VA_ARGS__; } #endif -class bad_variant_access : public std::exception { -public: - virtual const char *what() const noexcept override - { - return "bad_variant_access"; - } -}; + class bad_variant_access : public std::exception { + public: + virtual const char *what() const noexcept override { return "bad_variant_access"; } + }; -[[noreturn]] inline void -throw_bad_variant_access() -{ + [[noreturn]] inline void throw_bad_variant_access() { #ifdef MPARK_EXCEPTIONS throw bad_variant_access{}; #else std::terminate(); MPARK_BUILTIN_UNREACHABLE; #endif -} + } -template -class variant; + template + class variant; -template -struct variant_size; + template + struct variant_size; #ifdef MPARK_VARIABLE_TEMPLATES -template -constexpr std::size_t variant_size_v = variant_size::value; + template + constexpr std::size_t variant_size_v = variant_size::value; #endif -template -struct variant_size : variant_size {}; + template + struct variant_size : variant_size {}; -template -struct variant_size : variant_size {}; + template + struct variant_size : variant_size {}; -template -struct variant_size : variant_size {}; + template + struct variant_size : variant_size {}; -template -struct variant_size> : lib::size_constant {}; + template + struct variant_size> : lib::size_constant {}; -template -struct variant_alternative; + template + struct variant_alternative; -template -using variant_alternative_t = typename variant_alternative::type; + template + using variant_alternative_t = typename variant_alternative::type; -template -struct variant_alternative - : std::add_const> {}; + template + struct variant_alternative + : std::add_const> {}; -template -struct variant_alternative - : std::add_volatile> {}; + template + struct variant_alternative + : std::add_volatile> {}; -template -struct variant_alternative - : std::add_cv> {}; + template + struct variant_alternative + : std::add_cv> {}; -template -struct variant_alternative> { + template + struct variant_alternative> { static_assert(I < sizeof...(Ts), "index out of bounds in `std::variant_alternative<>`"); using type = lib::type_pack_element_t; -}; + }; -constexpr std::size_t variant_npos = static_cast(-1); + constexpr std::size_t variant_npos = static_cast(-1); -namespace detail { + namespace detail { -constexpr std::size_t not_found = static_cast(-1); -constexpr std::size_t ambiguous = static_cast(-2); + constexpr std::size_t not_found = static_cast(-1); + constexpr std::size_t ambiguous = static_cast(-2); #ifdef MPARK_CPP14_CONSTEXPR -template -inline constexpr std::size_t -find_index() -{ - constexpr lib::array matches = { - {std::is_same::value...}}; - std::size_t result = not_found; - for (std::size_t i = 0; i < sizeof...(Ts); ++i) { + template + inline constexpr std::size_t find_index() { + constexpr lib::array matches = { + {std::is_same::value...} + }; + std::size_t result = not_found; + for (std::size_t i = 0; i < sizeof...(Ts); ++i) { if (matches[i]) { - if (result != not_found) { return ambiguous; } - result = i; + if (result != not_found) { + return ambiguous; + } + result = i; } + } + return result; } - return result; -} #else -inline constexpr std::size_t -find_index_impl(std::size_t result, std::size_t) -{ - return result; -} + inline constexpr std::size_t find_index_impl(std::size_t result, + std::size_t) { + return result; + } -template -inline constexpr std::size_t -find_index_impl(std::size_t result, std::size_t idx, bool b, Bs... bs) -{ - return b ? (result != not_found ? ambiguous - : find_index_impl(idx, idx + 1, bs...)) - : find_index_impl(result, idx + 1, bs...); -} + template + inline constexpr std::size_t find_index_impl(std::size_t result, + std::size_t idx, + bool b, + Bs... bs) { + return b ? (result != not_found ? ambiguous + : find_index_impl(idx, idx + 1, bs...)) + : find_index_impl(result, idx + 1, bs...); + } -template -inline constexpr std::size_t -find_index() -{ - return find_index_impl(not_found, 0, std::is_same::value...); -} + template + inline constexpr std::size_t find_index() { + return find_index_impl(not_found, 0, std::is_same::value...); + } #endif -template -using find_index_sfinae_impl = - lib::enable_if_t>; + template + using find_index_sfinae_impl = + lib::enable_if_t>; -template -using find_index_sfinae = find_index_sfinae_impl()>; + template + using find_index_sfinae = find_index_sfinae_impl()>; -template -struct find_index_checked_impl : lib::size_constant { - static_assert(I != not_found, "the specified type is not found."); - static_assert(I != ambiguous, "the specified type is ambiguous."); -}; + template + struct find_index_checked_impl : lib::size_constant { + static_assert(I != not_found, "the specified type is not found."); + static_assert(I != ambiguous, "the specified type is ambiguous."); + }; -template -using find_index_checked = find_index_checked_impl()>; + template + using find_index_checked = find_index_checked_impl()>; -struct valueless_t {}; + struct valueless_t {}; -enum class Trait { TriviallyAvailable, Available, Unavailable }; + enum class Trait { TriviallyAvailable, Available, Unavailable }; -template - class IsTriviallyAvailable, - template - class IsAvailable> -inline constexpr Trait -trait() -{ - return IsTriviallyAvailable::value ? Trait::TriviallyAvailable - : IsAvailable::value ? Trait::Available - : Trait::Unavailable; -} + template class IsTriviallyAvailable, + template class IsAvailable> + inline constexpr Trait trait() { + return IsTriviallyAvailable::value + ? Trait::TriviallyAvailable + : IsAvailable::value ? Trait::Available + : Trait::Unavailable; + } #ifdef MPARK_CPP14_CONSTEXPR -template -inline constexpr Trait -common_trait(Traits... traits_) -{ - Trait result = Trait::TriviallyAvailable; - lib::array traits = {{traits_...}}; - for (std::size_t i = 0; i < sizeof...(Traits); ++i) { + template + inline constexpr Trait common_trait(Traits... traits_) { + Trait result = Trait::TriviallyAvailable; + lib::array traits = {{traits_...}}; + for (std::size_t i = 0; i < sizeof...(Traits); ++i) { Trait t = traits[i]; - if (static_cast(t) > static_cast(result)) { result = t; } + if (static_cast(t) > static_cast(result)) { + result = t; + } + } + return result; } - return result; -} #else -inline constexpr Trait -common_trait_impl(Trait result) -{ - return result; -} + inline constexpr Trait common_trait_impl(Trait result) { return result; } -template -inline constexpr Trait -common_trait_impl(Trait result, Trait t, Traits... ts) -{ - return static_cast(t) > static_cast(result) - ? common_trait_impl(t, ts...) - : common_trait_impl(result, ts...); -} + template + inline constexpr Trait common_trait_impl(Trait result, + Trait t, + Traits... ts) { + return static_cast(t) > static_cast(result) + ? common_trait_impl(t, ts...) + : common_trait_impl(result, ts...); + } -template -inline constexpr Trait -common_trait(Traits... ts) -{ - return common_trait_impl(Trait::TriviallyAvailable, ts...); -} + template + inline constexpr Trait common_trait(Traits... ts) { + return common_trait_impl(Trait::TriviallyAvailable, ts...); + } #endif -template -struct traits { - static constexpr Trait copy_constructible_trait = - common_trait(trait()...); + template + struct traits { + static constexpr Trait copy_constructible_trait = + common_trait(trait()...); - static constexpr Trait move_constructible_trait = - common_trait(trait()...); + static constexpr Trait move_constructible_trait = + common_trait(trait()...); - static constexpr Trait copy_assignable_trait = - common_trait(copy_constructible_trait, - trait()...); + static constexpr Trait copy_assignable_trait = + common_trait(copy_constructible_trait, + trait()...); - static constexpr Trait move_assignable_trait = - common_trait(move_constructible_trait, - trait()...); + static constexpr Trait move_assignable_trait = + common_trait(move_constructible_trait, + trait()...); - static constexpr Trait destructible_trait = common_trait( - trait()...); -}; + static constexpr Trait destructible_trait = + common_trait(trait()...); + }; -namespace access { + namespace access { -struct recursive_union { + struct recursive_union { #ifdef MPARK_RETURN_TYPE_DEDUCTION - template - inline static constexpr auto &&get_alt(V &&v, in_place_index_t<0>) - { - return lib::forward(v).head_; - } + template + inline static constexpr auto &&get_alt(V &&v, in_place_index_t<0>) { + return lib::forward(v).head_; + } - template - inline static constexpr auto &&get_alt(V &&v, in_place_index_t) - { - return get_alt(lib::forward(v).tail_, in_place_index_t{}); - } + template + inline static constexpr auto &&get_alt(V &&v, in_place_index_t) { + return get_alt(lib::forward(v).tail_, in_place_index_t{}); + } #else - template - struct get_alt_impl { - template - inline constexpr AUTO_REFREF operator()(V &&v) const + template + struct get_alt_impl { + template + inline constexpr AUTO_REFREF operator()(V &&v) const AUTO_REFREF_RETURN(get_alt_impl{}(lib::forward(v).tail_)) - }; + }; - template - struct get_alt_impl<0, Dummy> { - template - inline constexpr AUTO_REFREF operator()(V &&v) const + template + struct get_alt_impl<0, Dummy> { + template + inline constexpr AUTO_REFREF operator()(V &&v) const AUTO_REFREF_RETURN(lib::forward(v).head_) - }; + }; - template - inline static constexpr AUTO_REFREF get_alt(V &&v, in_place_index_t) - AUTO_REFREF_RETURN(get_alt_impl{}(lib::forward(v))) + template + inline static constexpr AUTO_REFREF get_alt(V &&v, in_place_index_t) + AUTO_REFREF_RETURN(get_alt_impl{}(lib::forward(v))) #endif -}; + }; -struct base { - template - inline static constexpr AUTO_REFREF get_alt(V &&v) + struct base { + template + inline static constexpr AUTO_REFREF get_alt(V &&v) #ifdef _MSC_VER - AUTO_REFREF_RETURN(recursive_union::get_alt(lib::forward(v).data_, - in_place_index_t{})) + AUTO_REFREF_RETURN(recursive_union::get_alt( + lib::forward(v).data_, in_place_index_t{})) #else - AUTO_REFREF_RETURN(recursive_union::get_alt(data(lib::forward(v)), - in_place_index_t{})) + AUTO_REFREF_RETURN(recursive_union::get_alt( + data(lib::forward(v)), in_place_index_t{})) #endif -}; + }; -struct variant { - template - inline static constexpr AUTO_REFREF get_alt(V &&v) - AUTO_REFREF_RETURN(base::get_alt(lib::forward(v).impl_)) -}; + struct variant { + template + inline static constexpr AUTO_REFREF get_alt(V &&v) + AUTO_REFREF_RETURN(base::get_alt(lib::forward(v).impl_)) + }; -}// namespace access + } // namespace access -namespace visitation { + namespace visitation { #if defined(MPARK_CPP14_CONSTEXPR) && !defined(_MSC_VER) #define MPARK_VARIANT_SWITCH_VISIT #endif -struct base { - template - using dispatch_result_t = - decltype(lib::invoke(std::declval(), - access::base::get_alt<0>(std::declval())...)); + struct base { + template + using dispatch_result_t = decltype( + lib::invoke(std::declval(), + access::base::get_alt<0>(std::declval())...)); - template - struct expected { - template - inline static constexpr bool but_got() - { + template + struct expected { + template + inline static constexpr bool but_got() { return std::is_same::value; - } - }; + } + }; - template - struct visit_return_type_check { - static_assert( - expected::template but_got(), - "`visit` requires the visitor to have a single return type"); + template + struct visit_return_type_check { + static_assert( + expected::template but_got(), + "`visit` requires the visitor to have a single return type"); - template - inline static constexpr DECLTYPE_AUTO invoke(Visitor &&visitor, - Alts &&...alts) + template + inline static constexpr DECLTYPE_AUTO invoke(Visitor &&visitor, + Alts &&... alts) DECLTYPE_AUTO_RETURN(lib::invoke(lib::forward(visitor), lib::forward(alts)...)) - }; + }; #ifdef MPARK_VARIANT_SWITCH_VISIT - template - struct dispatcher; + template + struct dispatcher; - template - struct dispatcher { - template - MPARK_ALWAYS_INLINE static constexpr R - dispatch(F &&, typename ITs::type &&..., Vs &&...) - { + template + struct dispatcher { + template + MPARK_ALWAYS_INLINE static constexpr R dispatch( + F &&, typename ITs::type &&..., Vs &&...) { MPARK_BUILTIN_UNREACHABLE; - } + } - template - MPARK_ALWAYS_INLINE static constexpr R dispatch_case(F &&, Vs &&...) - { + template + MPARK_ALWAYS_INLINE static constexpr R dispatch_case(F &&, Vs &&...) { MPARK_BUILTIN_UNREACHABLE; - } + } - template - MPARK_ALWAYS_INLINE static constexpr R - dispatch_at(std::size_t, F &&, Vs &&...) - { + template + MPARK_ALWAYS_INLINE static constexpr R dispatch_at(std::size_t, + F &&, + Vs &&...) { MPARK_BUILTIN_UNREACHABLE; - } - }; + } + }; - template - struct dispatcher { - template - MPARK_ALWAYS_INLINE static constexpr R - dispatch(F &&f, typename ITs::type &&...visited_vs) - { + template + struct dispatcher { + template + MPARK_ALWAYS_INLINE static constexpr R dispatch( + F &&f, typename ITs::type &&... visited_vs) { using Expected = R; using Actual = decltype(lib::invoke( lib::forward(f), @@ -1285,227 +1230,160 @@ struct base { lib::forward(f), access::base::get_alt( lib::forward(visited_vs))...); - } + } - template - MPARK_ALWAYS_INLINE static constexpr R - dispatch(F &&f, typename ITs::type &&...visited_vs, V &&v, Vs &&...vs) - { -#define MPARK_DISPATCH(I) \ - dispatcher<(I < lib::decay_t::size()), R, ITs..., \ - lib::indexed_type>:: \ - template dispatch<0>(lib::forward(f), \ - lib::forward(visited_vs)..., \ - lib::forward(v), lib::forward(vs)...) + template + MPARK_ALWAYS_INLINE static constexpr R dispatch( + F &&f, typename ITs::type &&... visited_vs, V &&v, Vs &&... vs) { +#define MPARK_DISPATCH(I) \ + dispatcher<(I < lib::decay_t::size()), \ + R, \ + ITs..., \ + lib::indexed_type>:: \ + template dispatch<0>(lib::forward(f), \ + lib::forward(visited_vs)..., \ + lib::forward(v), \ + lib::forward(vs)...) -#define MPARK_DEFAULT(I) \ - dispatcher<(I < lib::decay_t::size()), R, ITs...>::template dispatch< \ - I>(lib::forward(f), \ - lib::forward(visited_vs)..., \ - lib::forward(v), lib::forward(vs)...) +#define MPARK_DEFAULT(I) \ + dispatcher<(I < lib::decay_t::size()), R, ITs...>::template dispatch( \ + lib::forward(f), \ + lib::forward(visited_vs)..., \ + lib::forward(v), \ + lib::forward(vs)...) switch (v.index()) { - case B + 0: - return MPARK_DISPATCH(B + 0); - case B + 1: - return MPARK_DISPATCH(B + 1); - case B + 2: - return MPARK_DISPATCH(B + 2); - case B + 3: - return MPARK_DISPATCH(B + 3); - case B + 4: - return MPARK_DISPATCH(B + 4); - case B + 5: - return MPARK_DISPATCH(B + 5); - case B + 6: - return MPARK_DISPATCH(B + 6); - case B + 7: - return MPARK_DISPATCH(B + 7); - case B + 8: - return MPARK_DISPATCH(B + 8); - case B + 9: - return MPARK_DISPATCH(B + 9); - case B + 10: - return MPARK_DISPATCH(B + 10); - case B + 11: - return MPARK_DISPATCH(B + 11); - case B + 12: - return MPARK_DISPATCH(B + 12); - case B + 13: - return MPARK_DISPATCH(B + 13); - case B + 14: - return MPARK_DISPATCH(B + 14); - case B + 15: - return MPARK_DISPATCH(B + 15); - case B + 16: - return MPARK_DISPATCH(B + 16); - case B + 17: - return MPARK_DISPATCH(B + 17); - case B + 18: - return MPARK_DISPATCH(B + 18); - case B + 19: - return MPARK_DISPATCH(B + 19); - case B + 20: - return MPARK_DISPATCH(B + 20); - case B + 21: - return MPARK_DISPATCH(B + 21); - case B + 22: - return MPARK_DISPATCH(B + 22); - case B + 23: - return MPARK_DISPATCH(B + 23); - case B + 24: - return MPARK_DISPATCH(B + 24); - case B + 25: - return MPARK_DISPATCH(B + 25); - case B + 26: - return MPARK_DISPATCH(B + 26); - case B + 27: - return MPARK_DISPATCH(B + 27); - case B + 28: - return MPARK_DISPATCH(B + 28); - case B + 29: - return MPARK_DISPATCH(B + 29); - case B + 30: - return MPARK_DISPATCH(B + 30); - case B + 31: - return MPARK_DISPATCH(B + 31); - default: - return MPARK_DEFAULT(B + 32); + case B + 0: return MPARK_DISPATCH(B + 0); + case B + 1: return MPARK_DISPATCH(B + 1); + case B + 2: return MPARK_DISPATCH(B + 2); + case B + 3: return MPARK_DISPATCH(B + 3); + case B + 4: return MPARK_DISPATCH(B + 4); + case B + 5: return MPARK_DISPATCH(B + 5); + case B + 6: return MPARK_DISPATCH(B + 6); + case B + 7: return MPARK_DISPATCH(B + 7); + case B + 8: return MPARK_DISPATCH(B + 8); + case B + 9: return MPARK_DISPATCH(B + 9); + case B + 10: return MPARK_DISPATCH(B + 10); + case B + 11: return MPARK_DISPATCH(B + 11); + case B + 12: return MPARK_DISPATCH(B + 12); + case B + 13: return MPARK_DISPATCH(B + 13); + case B + 14: return MPARK_DISPATCH(B + 14); + case B + 15: return MPARK_DISPATCH(B + 15); + case B + 16: return MPARK_DISPATCH(B + 16); + case B + 17: return MPARK_DISPATCH(B + 17); + case B + 18: return MPARK_DISPATCH(B + 18); + case B + 19: return MPARK_DISPATCH(B + 19); + case B + 20: return MPARK_DISPATCH(B + 20); + case B + 21: return MPARK_DISPATCH(B + 21); + case B + 22: return MPARK_DISPATCH(B + 22); + case B + 23: return MPARK_DISPATCH(B + 23); + case B + 24: return MPARK_DISPATCH(B + 24); + case B + 25: return MPARK_DISPATCH(B + 25); + case B + 26: return MPARK_DISPATCH(B + 26); + case B + 27: return MPARK_DISPATCH(B + 27); + case B + 28: return MPARK_DISPATCH(B + 28); + case B + 29: return MPARK_DISPATCH(B + 29); + case B + 30: return MPARK_DISPATCH(B + 30); + case B + 31: return MPARK_DISPATCH(B + 31); + default: return MPARK_DEFAULT(B + 32); } #undef MPARK_DEFAULT #undef MPARK_DISPATCH - } + } - template - MPARK_ALWAYS_INLINE static constexpr R dispatch_case(F &&f, Vs &&...vs) - { + template + MPARK_ALWAYS_INLINE static constexpr R dispatch_case(F &&f, + Vs &&... vs) { using Expected = R; - using Actual = decltype(lib::invoke( - lib::forward(f), - access::base::get_alt(lib::forward(vs))...)); + using Actual = decltype( + lib::invoke(lib::forward(f), + access::base::get_alt(lib::forward(vs))...)); return visit_return_type_check::invoke( lib::forward(f), access::base::get_alt(lib::forward(vs))...); - } + } - template - MPARK_ALWAYS_INLINE static constexpr R - dispatch_at(std::size_t index, F &&f, V &&v, Vs &&...vs) - { - static_assert(lib::all<(lib::decay_t::size() - == lib::decay_t::size())...>::value, + template + MPARK_ALWAYS_INLINE static constexpr R dispatch_at(std::size_t index, + F &&f, + V &&v, + Vs &&... vs) { + static_assert(lib::all<(lib::decay_t::size() == + lib::decay_t::size())...>::value, "all of the variants must be the same size."); -#define MPARK_DISPATCH_AT(I) \ - dispatcher<(I < lib::decay_t::size()), R>::template dispatch_case( \ - lib::forward(f), lib::forward(v), lib::forward(vs)...) +#define MPARK_DISPATCH_AT(I) \ + dispatcher<(I < lib::decay_t::size()), R>::template dispatch_case( \ + lib::forward(f), lib::forward(v), lib::forward(vs)...) -#define MPARK_DEFAULT(I) \ - dispatcher<(I < lib::decay_t::size()), R>::template dispatch_at( \ - index, lib::forward(f), lib::forward(v), \ - lib::forward(vs)...) +#define MPARK_DEFAULT(I) \ + dispatcher<(I < lib::decay_t::size()), R>::template dispatch_at( \ + index, lib::forward(f), lib::forward(v), lib::forward(vs)...) switch (index) { - case B + 0: - return MPARK_DISPATCH_AT(B + 0); - case B + 1: - return MPARK_DISPATCH_AT(B + 1); - case B + 2: - return MPARK_DISPATCH_AT(B + 2); - case B + 3: - return MPARK_DISPATCH_AT(B + 3); - case B + 4: - return MPARK_DISPATCH_AT(B + 4); - case B + 5: - return MPARK_DISPATCH_AT(B + 5); - case B + 6: - return MPARK_DISPATCH_AT(B + 6); - case B + 7: - return MPARK_DISPATCH_AT(B + 7); - case B + 8: - return MPARK_DISPATCH_AT(B + 8); - case B + 9: - return MPARK_DISPATCH_AT(B + 9); - case B + 10: - return MPARK_DISPATCH_AT(B + 10); - case B + 11: - return MPARK_DISPATCH_AT(B + 11); - case B + 12: - return MPARK_DISPATCH_AT(B + 12); - case B + 13: - return MPARK_DISPATCH_AT(B + 13); - case B + 14: - return MPARK_DISPATCH_AT(B + 14); - case B + 15: - return MPARK_DISPATCH_AT(B + 15); - case B + 16: - return MPARK_DISPATCH_AT(B + 16); - case B + 17: - return MPARK_DISPATCH_AT(B + 17); - case B + 18: - return MPARK_DISPATCH_AT(B + 18); - case B + 19: - return MPARK_DISPATCH_AT(B + 19); - case B + 20: - return MPARK_DISPATCH_AT(B + 20); - case B + 21: - return MPARK_DISPATCH_AT(B + 21); - case B + 22: - return MPARK_DISPATCH_AT(B + 22); - case B + 23: - return MPARK_DISPATCH_AT(B + 23); - case B + 24: - return MPARK_DISPATCH_AT(B + 24); - case B + 25: - return MPARK_DISPATCH_AT(B + 25); - case B + 26: - return MPARK_DISPATCH_AT(B + 26); - case B + 27: - return MPARK_DISPATCH_AT(B + 27); - case B + 28: - return MPARK_DISPATCH_AT(B + 28); - case B + 29: - return MPARK_DISPATCH_AT(B + 29); - case B + 30: - return MPARK_DISPATCH_AT(B + 30); - case B + 31: - return MPARK_DISPATCH_AT(B + 31); - default: - return MPARK_DEFAULT(B + 32); + case B + 0: return MPARK_DISPATCH_AT(B + 0); + case B + 1: return MPARK_DISPATCH_AT(B + 1); + case B + 2: return MPARK_DISPATCH_AT(B + 2); + case B + 3: return MPARK_DISPATCH_AT(B + 3); + case B + 4: return MPARK_DISPATCH_AT(B + 4); + case B + 5: return MPARK_DISPATCH_AT(B + 5); + case B + 6: return MPARK_DISPATCH_AT(B + 6); + case B + 7: return MPARK_DISPATCH_AT(B + 7); + case B + 8: return MPARK_DISPATCH_AT(B + 8); + case B + 9: return MPARK_DISPATCH_AT(B + 9); + case B + 10: return MPARK_DISPATCH_AT(B + 10); + case B + 11: return MPARK_DISPATCH_AT(B + 11); + case B + 12: return MPARK_DISPATCH_AT(B + 12); + case B + 13: return MPARK_DISPATCH_AT(B + 13); + case B + 14: return MPARK_DISPATCH_AT(B + 14); + case B + 15: return MPARK_DISPATCH_AT(B + 15); + case B + 16: return MPARK_DISPATCH_AT(B + 16); + case B + 17: return MPARK_DISPATCH_AT(B + 17); + case B + 18: return MPARK_DISPATCH_AT(B + 18); + case B + 19: return MPARK_DISPATCH_AT(B + 19); + case B + 20: return MPARK_DISPATCH_AT(B + 20); + case B + 21: return MPARK_DISPATCH_AT(B + 21); + case B + 22: return MPARK_DISPATCH_AT(B + 22); + case B + 23: return MPARK_DISPATCH_AT(B + 23); + case B + 24: return MPARK_DISPATCH_AT(B + 24); + case B + 25: return MPARK_DISPATCH_AT(B + 25); + case B + 26: return MPARK_DISPATCH_AT(B + 26); + case B + 27: return MPARK_DISPATCH_AT(B + 27); + case B + 28: return MPARK_DISPATCH_AT(B + 28); + case B + 29: return MPARK_DISPATCH_AT(B + 29); + case B + 30: return MPARK_DISPATCH_AT(B + 30); + case B + 31: return MPARK_DISPATCH_AT(B + 31); + default: return MPARK_DEFAULT(B + 32); } #undef MPARK_DEFAULT #undef MPARK_DISPATCH_AT - } - }; + } + }; #else - template - inline static constexpr const T &at(const T &elem) noexcept - { - return elem; - } + template + inline static constexpr const T &at(const T &elem) noexcept { + return elem; + } - template - inline static constexpr const lib::remove_all_extents_t & - at(const lib::array &elems, std::size_t i, Is... is) noexcept - { - return at(elems[i], is...); - } + template + inline static constexpr const lib::remove_all_extents_t &at( + const lib::array &elems, std::size_t i, Is... is) noexcept { + return at(elems[i], is...); + } - template - inline static constexpr lib::array, sizeof...(Fs) + 1> - make_farray(F &&f, Fs &&...fs) - { - return {{lib::forward(f), lib::forward(fs)...}}; - } + template + inline static constexpr lib::array, sizeof...(Fs) + 1> + make_farray(F &&f, Fs &&... fs) { + return {{lib::forward(f), lib::forward(fs)...}}; + } - template - struct make_fmatrix_impl { + template + struct make_fmatrix_impl { - template - inline static constexpr dispatch_result_t dispatch(F &&f, - Vs &&...vs) - { + template + inline static constexpr dispatch_result_t dispatch( + F &&f, Vs &&... vs) { using Expected = dispatch_result_t; using Actual = decltype(lib::invoke( lib::forward(f), @@ -1513,859 +1391,823 @@ struct base { return visit_return_type_check::invoke( lib::forward(f), access::base::get_alt(lib::forward(vs))...); - } + } #ifdef MPARK_RETURN_TYPE_DEDUCTION - template - inline static constexpr auto impl(lib::index_sequence) - { + template + inline static constexpr auto impl(lib::index_sequence) { return &dispatch; - } + } - template - inline static constexpr auto - impl(Is, lib::index_sequence, Ls... ls) - { + template + inline static constexpr auto impl(Is, + lib::index_sequence, + Ls... ls) { return make_farray(impl(lib::push_back_t{}, ls...)...); - } + } #else - template - struct impl; + template + struct impl; - template - struct impl> { + template + struct impl> { inline constexpr AUTO operator()() const - AUTO_RETURN(&dispatch) - }; + AUTO_RETURN(&dispatch) + }; - template - struct impl, Ls...> { - inline constexpr AUTO operator()() const AUTO_RETURN( - make_farray(impl, Ls...>{}()...)) - }; + template + struct impl, Ls...> { + inline constexpr AUTO operator()() const + AUTO_RETURN( + make_farray(impl, Ls...>{}()...)) + }; #endif - }; + }; #ifdef MPARK_RETURN_TYPE_DEDUCTION - template - inline static constexpr auto make_fmatrix() - { - return make_fmatrix_impl::impl( - lib::index_sequence<>{}, - lib::make_index_sequence::size()>{}...); - } + template + inline static constexpr auto make_fmatrix() { + return make_fmatrix_impl::impl( + lib::index_sequence<>{}, + lib::make_index_sequence::size()>{}...); + } #else - template - inline static constexpr AUTO make_fmatrix() - AUTO_RETURN(typename make_fmatrix_impl::template impl< - lib::index_sequence<>, - lib::make_index_sequence::size()>...>{}()) + template + inline static constexpr AUTO make_fmatrix() + AUTO_RETURN( + typename make_fmatrix_impl::template impl< + lib::index_sequence<>, + lib::make_index_sequence::size()>...>{}()) #endif - template - struct make_fdiagonal_impl { - template - inline static constexpr dispatch_result_t dispatch(F &&f, - Vs &&...vs) - { + template + struct make_fdiagonal_impl { + template + inline static constexpr dispatch_result_t dispatch( + F &&f, Vs &&... vs) { using Expected = dispatch_result_t; - using Actual = decltype(lib::invoke( - lib::forward(f), - access::base::get_alt(lib::forward(vs))...)); + using Actual = decltype( + lib::invoke(lib::forward(f), + access::base::get_alt(lib::forward(vs))...)); return visit_return_type_check::invoke( lib::forward(f), access::base::get_alt(lib::forward(vs))...); - } + } - template - inline static constexpr AUTO impl(lib::index_sequence) + template + inline static constexpr AUTO impl(lib::index_sequence) AUTO_RETURN(make_farray(&dispatch...)) - }; + }; - template - inline static constexpr auto make_fdiagonal() - -> decltype(make_fdiagonal_impl::impl( - lib::make_index_sequence::size()>{})) - { - static_assert(lib::all<(lib::decay_t::size() - == lib::decay_t::size())...>::value, - "all of the variants must be the same size."); - return make_fdiagonal_impl::impl( - lib::make_index_sequence::size()>{}); - } -#endif -}; - -#if !defined(MPARK_VARIANT_SWITCH_VISIT) \ - && (!defined(_MSC_VER) || _MSC_VER >= 1910) -template -using fmatrix_t = decltype(base::make_fmatrix()); - -template -struct fmatrix { - static constexpr fmatrix_t value = base::make_fmatrix(); -}; - -template -constexpr fmatrix_t fmatrix::value; - -template -using fdiagonal_t = decltype(base::make_fdiagonal()); - -template -struct fdiagonal { - static constexpr fdiagonal_t value = - base::make_fdiagonal(); -}; - -template -constexpr fdiagonal_t fdiagonal::value; -#endif - -struct alt { - template - inline static constexpr DECLTYPE_AUTO visit_alt(Visitor &&visitor, - Vs &&...vs) -#ifdef MPARK_VARIANT_SWITCH_VISIT - DECLTYPE_AUTO_RETURN( - base::dispatcher(vs)))...>>:: - template dispatch<0>(lib::forward(visitor), - as_base(lib::forward(vs))...)) -#elif !defined(_MSC_VER) || _MSC_VER >= 1910 - DECLTYPE_AUTO_RETURN( - base::at(fmatrix(vs)))...>::value, - vs.index()...)(lib::forward(visitor), - as_base(lib::forward(vs))...)) -#else - DECLTYPE_AUTO_RETURN(base::at( - base::make_fmatrix(vs)))...>(), - vs.index()...)(lib::forward(visitor), - as_base(lib::forward(vs))...)) -#endif - - template - inline static constexpr DECLTYPE_AUTO - visit_alt_at(std::size_t index, Visitor &&visitor, Vs &&...vs) -#ifdef MPARK_VARIANT_SWITCH_VISIT - DECLTYPE_AUTO_RETURN( - base::dispatcher< - true, - base::dispatch_result_t< - Visitor, - decltype(as_base(lib::forward(vs)))...>>:: - template dispatch_at<0>(index, - lib::forward(visitor), - as_base(lib::forward(vs))...)) -#elif !defined(_MSC_VER) || _MSC_VER >= 1910 - DECLTYPE_AUTO_RETURN(base::at( - fdiagonal(vs)))...>::value, - index)(lib::forward(visitor), - as_base(lib::forward(vs))...)) -#else - DECLTYPE_AUTO_RETURN( - base::at(base::make_fdiagonal< - Visitor &&, - decltype(as_base(lib::forward(vs)))...>(), - index)(lib::forward(visitor), - as_base(lib::forward(vs))...)) -#endif -}; - -struct variant { -private: - template - struct visitor { - template - inline static constexpr bool does_not_handle() - { - return lib::is_invocable::value; + template + inline static constexpr auto make_fdiagonal() + -> decltype(make_fdiagonal_impl::impl( + lib::make_index_sequence::size()>{})) { + static_assert(lib::all<(lib::decay_t::size() == + lib::decay_t::size())...>::value, + "all of the variants must be the same size."); + return make_fdiagonal_impl::impl( + lib::make_index_sequence::size()>{}); } - }; +#endif + }; - template - struct visit_exhaustiveness_check { - static_assert(visitor::template does_not_handle(), - "`visit` requires the visitor to be exhaustive."); +#if !defined(MPARK_VARIANT_SWITCH_VISIT) && \ + (!defined(_MSC_VER) || _MSC_VER >= 1910) + template + using fmatrix_t = decltype(base::make_fmatrix()); - inline static constexpr DECLTYPE_AUTO invoke(Visitor &&visitor, - Values &&...values) + template + struct fmatrix { + static constexpr fmatrix_t value = + base::make_fmatrix(); + }; + + template + constexpr fmatrix_t fmatrix::value; + + template + using fdiagonal_t = decltype(base::make_fdiagonal()); + + template + struct fdiagonal { + static constexpr fdiagonal_t value = + base::make_fdiagonal(); + }; + + template + constexpr fdiagonal_t fdiagonal::value; +#endif + + struct alt { + template + inline static constexpr DECLTYPE_AUTO visit_alt(Visitor &&visitor, + Vs &&... vs) +#ifdef MPARK_VARIANT_SWITCH_VISIT + DECLTYPE_AUTO_RETURN( + base::dispatcher< + true, + base::dispatch_result_t(vs)))...>>:: + template dispatch<0>(lib::forward(visitor), + as_base(lib::forward(vs))...)) +#elif !defined(_MSC_VER) || _MSC_VER >= 1910 + DECLTYPE_AUTO_RETURN(base::at( + fmatrix(vs)))...>::value, + vs.index()...)(lib::forward(visitor), + as_base(lib::forward(vs))...)) +#else + DECLTYPE_AUTO_RETURN(base::at( + base::make_fmatrix(vs)))...>(), + vs.index()...)(lib::forward(visitor), + as_base(lib::forward(vs))...)) +#endif + + template + inline static constexpr DECLTYPE_AUTO visit_alt_at(std::size_t index, + Visitor &&visitor, + Vs &&... vs) +#ifdef MPARK_VARIANT_SWITCH_VISIT + DECLTYPE_AUTO_RETURN( + base::dispatcher< + true, + base::dispatch_result_t(vs)))...>>:: + template dispatch_at<0>(index, + lib::forward(visitor), + as_base(lib::forward(vs))...)) +#elif !defined(_MSC_VER) || _MSC_VER >= 1910 + DECLTYPE_AUTO_RETURN(base::at( + fdiagonal(vs)))...>::value, + index)(lib::forward(visitor), + as_base(lib::forward(vs))...)) +#else + DECLTYPE_AUTO_RETURN(base::at( + base::make_fdiagonal(vs)))...>(), + index)(lib::forward(visitor), + as_base(lib::forward(vs))...)) +#endif + }; + + struct variant { + private: + template + struct visitor { + template + inline static constexpr bool does_not_handle() { + return lib::is_invocable::value; + } + }; + + template + struct visit_exhaustiveness_check { + static_assert(visitor::template does_not_handle(), + "`visit` requires the visitor to be exhaustive."); + + inline static constexpr DECLTYPE_AUTO invoke(Visitor &&visitor, + Values &&... values) DECLTYPE_AUTO_RETURN(lib::invoke(lib::forward(visitor), lib::forward(values)...)) - }; + }; - template - struct value_visitor { - Visitor &&visitor_; + template + struct value_visitor { + Visitor &&visitor_; - template - inline constexpr DECLTYPE_AUTO operator()(Alts &&...alts) const + template + inline constexpr DECLTYPE_AUTO operator()(Alts &&... alts) const DECLTYPE_AUTO_RETURN( visit_exhaustiveness_check< Visitor, decltype((lib::forward(alts).value))...>:: invoke(lib::forward(visitor_), lib::forward(alts).value...)) - }; + }; - template - inline static constexpr AUTO make_value_visitor(Visitor &&visitor) - AUTO_RETURN(value_visitor{lib::forward(visitor)}) + template + inline static constexpr AUTO make_value_visitor(Visitor &&visitor) + AUTO_RETURN(value_visitor{lib::forward(visitor)}) - public - : template - inline static constexpr DECLTYPE_AUTO - visit_alt(Visitor &&visitor, Vs &&...vs) DECLTYPE_AUTO_RETURN( - alt::visit_alt(lib::forward(visitor), - lib::forward(vs).impl_...)) + public: + template + inline static constexpr DECLTYPE_AUTO visit_alt(Visitor &&visitor, + Vs &&... vs) + DECLTYPE_AUTO_RETURN(alt::visit_alt(lib::forward(visitor), + lib::forward(vs).impl_...)) - template - inline static constexpr DECLTYPE_AUTO - visit_alt_at(std::size_t index, Visitor &&visitor, Vs &&...vs) - DECLTYPE_AUTO_RETURN( - alt::visit_alt_at(index, - lib::forward(visitor), - lib::forward(vs).impl_...)) + template + inline static constexpr DECLTYPE_AUTO visit_alt_at(std::size_t index, + Visitor &&visitor, + Vs &&... vs) + DECLTYPE_AUTO_RETURN( + alt::visit_alt_at(index, + lib::forward(visitor), + lib::forward(vs).impl_...)) - template - inline static constexpr DECLTYPE_AUTO - visit_value(Visitor &&visitor, Vs &&...vs) DECLTYPE_AUTO_RETURN( + template + inline static constexpr DECLTYPE_AUTO visit_value(Visitor &&visitor, + Vs &&... vs) + DECLTYPE_AUTO_RETURN( visit_alt(make_value_visitor(lib::forward(visitor)), lib::forward(vs)...)) - template - inline static constexpr DECLTYPE_AUTO - visit_value_at(std::size_t index, Visitor &&visitor, Vs &&...vs) - DECLTYPE_AUTO_RETURN(visit_alt_at( - index, - make_value_visitor(lib::forward(visitor)), - lib::forward(vs)...)) -}; + template + inline static constexpr DECLTYPE_AUTO visit_value_at(std::size_t index, + Visitor &&visitor, + Vs &&... vs) + DECLTYPE_AUTO_RETURN( + visit_alt_at(index, + make_value_visitor(lib::forward(visitor)), + lib::forward(vs)...)) + }; -}// namespace visitation + } // namespace visitation -template -struct alt { - using value_type = T; + template + struct alt { + using value_type = T; #ifdef _MSC_VER #pragma warning(push) #pragma warning(disable : 4244) #endif - template - inline explicit constexpr alt(in_place_t, Args &&...args) - : value(lib::forward(args)...) - {} + template + inline explicit constexpr alt(in_place_t, Args &&... args) + : value(lib::forward(args)...) {} #ifdef _MSC_VER #pragma warning(pop) #endif - T value; -}; + T value; + }; -template -union recursive_union; + template + union recursive_union; -template -union recursive_union {}; + template + union recursive_union {}; -#define MPARK_VARIANT_RECURSIVE_UNION(destructible_trait, destructor) \ - template \ - union recursive_union { \ - public: \ - inline explicit constexpr recursive_union(valueless_t) noexcept \ - : dummy_{} \ - {} \ - \ - template \ - inline explicit constexpr recursive_union(in_place_index_t<0>, \ - Args &&...args) \ - : head_(in_place_t{}, lib::forward(args)...) \ - {} \ - \ - template \ - inline explicit constexpr recursive_union(in_place_index_t, \ - Args &&...args) \ - : tail_(in_place_index_t{}, lib::forward(args)...) \ - {} \ - \ - recursive_union(const recursive_union &) = default; \ - recursive_union(recursive_union &&) = default; \ - \ - destructor \ - \ - recursive_union & \ - operator=(const recursive_union &) = default; \ - recursive_union &operator=(recursive_union &&) = default; \ - \ - private: \ - char dummy_; \ - alt head_; \ - recursive_union tail_; \ - \ - friend struct access::recursive_union; \ - } +#define MPARK_VARIANT_RECURSIVE_UNION(destructible_trait, destructor) \ + template \ + union recursive_union { \ + public: \ + inline explicit constexpr recursive_union(valueless_t) noexcept \ + : dummy_{} {} \ + \ + template \ + inline explicit constexpr recursive_union(in_place_index_t<0>, \ + Args &&... args) \ + : head_(in_place_t{}, lib::forward(args)...) {} \ + \ + template \ + inline explicit constexpr recursive_union(in_place_index_t, \ + Args &&... args) \ + : tail_(in_place_index_t{}, lib::forward(args)...) {} \ + \ + recursive_union(const recursive_union &) = default; \ + recursive_union(recursive_union &&) = default; \ + \ + destructor \ + \ + recursive_union &operator=(const recursive_union &) = default; \ + recursive_union &operator=(recursive_union &&) = default; \ + \ + private: \ + char dummy_; \ + alt head_; \ + recursive_union tail_; \ + \ + friend struct access::recursive_union; \ + } -MPARK_VARIANT_RECURSIVE_UNION(Trait::TriviallyAvailable, - ~recursive_union() = default;); -MPARK_VARIANT_RECURSIVE_UNION(Trait::Available, ~recursive_union(){}); -MPARK_VARIANT_RECURSIVE_UNION(Trait::Unavailable, ~recursive_union() = delete;); + MPARK_VARIANT_RECURSIVE_UNION(Trait::TriviallyAvailable, + ~recursive_union() = default;); + MPARK_VARIANT_RECURSIVE_UNION(Trait::Available, + ~recursive_union() {}); + MPARK_VARIANT_RECURSIVE_UNION(Trait::Unavailable, + ~recursive_union() = delete;); #undef MPARK_VARIANT_RECURSIVE_UNION -using index_t = unsigned int; + using index_t = unsigned int; -template -class base { -public: - inline explicit constexpr base(valueless_t tag) noexcept - : data_(tag), - index_(static_cast(-1)) - {} + template + class base { + public: + inline explicit constexpr base(valueless_t tag) noexcept + : data_(tag), index_(static_cast(-1)) {} - template - inline explicit constexpr base(in_place_index_t, Args &&...args) - : data_(in_place_index_t{}, lib::forward(args)...), - index_(I) - {} + template + inline explicit constexpr base(in_place_index_t, Args &&... args) + : data_(in_place_index_t{}, lib::forward(args)...), + index_(I) {} - inline constexpr bool valueless_by_exception() const noexcept - { + inline constexpr bool valueless_by_exception() const noexcept { return index_ == static_cast(-1); - } + } - inline constexpr std::size_t index() const noexcept - { + inline constexpr std::size_t index() const noexcept { return valueless_by_exception() ? variant_npos : index_; - } + } -protected: - using data_t = recursive_union; + protected: + using data_t = recursive_union; - friend inline constexpr base &as_base(base &b) { return b; } + friend inline constexpr base &as_base(base &b) { return b; } + friend inline constexpr const base &as_base(const base &b) { return b; } + friend inline constexpr base &&as_base(base &&b) { return lib::move(b); } + friend inline constexpr const base &&as_base(const base &&b) { return lib::move(b); } - friend inline constexpr const base &as_base(const base &b) { return b; } + friend inline constexpr data_t &data(base &b) { return b.data_; } + friend inline constexpr const data_t &data(const base &b) { return b.data_; } + friend inline constexpr data_t &&data(base &&b) { return lib::move(b).data_; } + friend inline constexpr const data_t &&data(const base &&b) { return lib::move(b).data_; } - friend inline constexpr base &&as_base(base &&b) { return lib::move(b); } + inline static constexpr std::size_t size() { return sizeof...(Ts); } - friend inline constexpr const base &&as_base(const base &&b) - { - return lib::move(b); - } + data_t data_; + index_t index_; - friend inline constexpr data_t &data(base &b) { return b.data_; } + friend struct access::base; + friend struct visitation::base; + }; - friend inline constexpr const data_t &data(const base &b) - { - return b.data_; - } - - friend inline constexpr data_t &&data(base &&b) - { - return lib::move(b).data_; - } - - friend inline constexpr const data_t &&data(const base &&b) - { - return lib::move(b).data_; - } - - inline static constexpr std::size_t size() { return sizeof...(Ts); } - - data_t data_; - index_t index_; - - friend struct access::base; - friend struct visitation::base; -}; - -struct dtor { + struct dtor { #ifdef _MSC_VER #pragma warning(push) #pragma warning(disable : 4100) #endif - template - inline void operator()(Alt &alt) const noexcept - { - alt.~Alt(); - } + template + inline void operator()(Alt &alt) const noexcept { alt.~Alt(); } #ifdef _MSC_VER #pragma warning(pop) #endif -}; + }; #if !defined(_MSC_VER) || _MSC_VER >= 1910 #define MPARK_INHERITING_CTOR(type, base) using base::base; #else -#define MPARK_INHERITING_CTOR(type, base) \ - template \ - inline explicit constexpr type(Args &&...args) \ - : base(lib::forward(args)...) \ - {} +#define MPARK_INHERITING_CTOR(type, base) \ + template \ + inline explicit constexpr type(Args &&... args) \ + : base(lib::forward(args)...) {} #endif -template -class destructor; + template + class destructor; -#define MPARK_VARIANT_DESTRUCTOR(destructible_trait, definition, destroy) \ - template \ - class destructor, destructible_trait> \ - : public base { \ - using super = base; \ - \ - public: \ - MPARK_INHERITING_CTOR(destructor, super) \ - using super::operator=; \ - \ - destructor(const destructor &) = default; \ - destructor(destructor &&) = default; \ - definition destructor &operator=(const destructor &) = default; \ - destructor &operator=(destructor &&) = default; \ - \ - protected: \ - destroy \ - } +#define MPARK_VARIANT_DESTRUCTOR(destructible_trait, definition, destroy) \ + template \ + class destructor, destructible_trait> \ + : public base { \ + using super = base; \ + \ + public: \ + MPARK_INHERITING_CTOR(destructor, super) \ + using super::operator=; \ + \ + destructor(const destructor &) = default; \ + destructor(destructor &&) = default; \ + definition \ + destructor &operator=(const destructor &) = default; \ + destructor &operator=(destructor &&) = default; \ + \ + protected: \ + destroy \ + } -MPARK_VARIANT_DESTRUCTOR( - Trait::TriviallyAvailable, ~destructor() = default; - , inline void destroy() noexcept { - this->index_ = static_cast(-1); - }); + MPARK_VARIANT_DESTRUCTOR( + Trait::TriviallyAvailable, + ~destructor() = default;, + inline void destroy() noexcept { + this->index_ = static_cast(-1); + }); -MPARK_VARIANT_DESTRUCTOR( - Trait::Available, - ~destructor() { destroy(); }, - inline void destroy() noexcept { - if (!this->valueless_by_exception()) { + MPARK_VARIANT_DESTRUCTOR( + Trait::Available, + ~destructor() { destroy(); }, + inline void destroy() noexcept { + if (!this->valueless_by_exception()) { visitation::alt::visit_alt(dtor{}, *this); - } - this->index_ = static_cast(-1); - }); + } + this->index_ = static_cast(-1); + }); -MPARK_VARIANT_DESTRUCTOR(Trait::Unavailable, ~destructor() = delete; - , inline void destroy() noexcept = delete;); + MPARK_VARIANT_DESTRUCTOR( + Trait::Unavailable, + ~destructor() = delete;, + inline void destroy() noexcept = delete;); #undef MPARK_VARIANT_DESTRUCTOR -template -class constructor : public destructor { - using super = destructor; + template + class constructor : public destructor { + using super = destructor; -public: - MPARK_INHERITING_CTOR(constructor, super) - using super::operator=; + public: + MPARK_INHERITING_CTOR(constructor, super) + using super::operator=; -protected: + protected: #ifndef MPARK_GENERIC_LAMBDAS - struct ctor { - template - inline void operator()(LhsAlt &lhs_alt, RhsAlt &&rhs_alt) const - { - constructor::construct_alt(lhs_alt, - lib::forward(rhs_alt).value); + struct ctor { + template + inline void operator()(LhsAlt &lhs_alt, RhsAlt &&rhs_alt) const { + constructor::construct_alt(lhs_alt, + lib::forward(rhs_alt).value); } - }; + }; #endif - template - inline static T &construct_alt(alt &a, Args &&...args) - { + template + inline static T &construct_alt(alt &a, Args &&... args) { auto *result = ::new (static_cast(lib::addressof(a))) alt(in_place_t{}, lib::forward(args)...); return result->value; - } + } - template - inline static void generic_construct(constructor &lhs, Rhs &&rhs) - { + template + inline static void generic_construct(constructor &lhs, Rhs &&rhs) { lhs.destroy(); if (!rhs.valueless_by_exception()) { - visitation::alt::visit_alt_at( - rhs.index(), + visitation::alt::visit_alt_at( + rhs.index(), #ifdef MPARK_GENERIC_LAMBDAS - [](auto &lhs_alt, auto &&rhs_alt) { - constructor::construct_alt( - lhs_alt, - lib::forward(rhs_alt).value); - } + [](auto &lhs_alt, auto &&rhs_alt) { + constructor::construct_alt( + lhs_alt, lib::forward(rhs_alt).value); + } #else - ctor{} + ctor{} #endif - , - lhs, lib::forward(rhs)); - lhs.index_ = rhs.index_; + , + lhs, + lib::forward(rhs)); + lhs.index_ = rhs.index_; } - } -}; + } + }; -template -class move_constructor; + template + class move_constructor; -#define MPARK_VARIANT_MOVE_CONSTRUCTOR(move_constructible_trait, definition) \ - template \ - class move_constructor, move_constructible_trait> \ - : public constructor> { \ - using super = constructor>; \ - \ - public: \ - MPARK_INHERITING_CTOR(move_constructor, super) \ - using super::operator=; \ - \ - move_constructor(const move_constructor &) = default; \ - definition ~move_constructor() = default; \ - move_constructor &operator=(const move_constructor &) = default; \ - move_constructor &operator=(move_constructor &&) = default; \ - } +#define MPARK_VARIANT_MOVE_CONSTRUCTOR(move_constructible_trait, definition) \ + template \ + class move_constructor, move_constructible_trait> \ + : public constructor> { \ + using super = constructor>; \ + \ + public: \ + MPARK_INHERITING_CTOR(move_constructor, super) \ + using super::operator=; \ + \ + move_constructor(const move_constructor &) = default; \ + definition \ + ~move_constructor() = default; \ + move_constructor &operator=(const move_constructor &) = default; \ + move_constructor &operator=(move_constructor &&) = default; \ + } -MPARK_VARIANT_MOVE_CONSTRUCTOR( - Trait::TriviallyAvailable, - move_constructor(move_constructor &&that) = default;); + MPARK_VARIANT_MOVE_CONSTRUCTOR( + Trait::TriviallyAvailable, + move_constructor(move_constructor &&that) = default;); -MPARK_VARIANT_MOVE_CONSTRUCTOR( - Trait::Available, - move_constructor(move_constructor &&that) noexcept( - lib::all::value...>::value) - : move_constructor(valueless_t{}) { - this->generic_construct(*this, lib::move(that)); - }); + MPARK_VARIANT_MOVE_CONSTRUCTOR( + Trait::Available, + move_constructor(move_constructor &&that) noexcept( + lib::all::value...>::value) + : move_constructor(valueless_t{}) { + this->generic_construct(*this, lib::move(that)); + }); -MPARK_VARIANT_MOVE_CONSTRUCTOR(Trait::Unavailable, - move_constructor(move_constructor &&) = delete;); + MPARK_VARIANT_MOVE_CONSTRUCTOR( + Trait::Unavailable, + move_constructor(move_constructor &&) = delete;); #undef MPARK_VARIANT_MOVE_CONSTRUCTOR -template -class copy_constructor; + template + class copy_constructor; -#define MPARK_VARIANT_COPY_CONSTRUCTOR(copy_constructible_trait, definition) \ - template \ - class copy_constructor, copy_constructible_trait> \ - : public move_constructor> { \ - using super = move_constructor>; \ - \ - public: \ - MPARK_INHERITING_CTOR(copy_constructor, super) \ - using super::operator=; \ - \ - definition copy_constructor(copy_constructor &&) = default; \ - ~copy_constructor() = default; \ - copy_constructor &operator=(const copy_constructor &) = default; \ - copy_constructor &operator=(copy_constructor &&) = default; \ - } +#define MPARK_VARIANT_COPY_CONSTRUCTOR(copy_constructible_trait, definition) \ + template \ + class copy_constructor, copy_constructible_trait> \ + : public move_constructor> { \ + using super = move_constructor>; \ + \ + public: \ + MPARK_INHERITING_CTOR(copy_constructor, super) \ + using super::operator=; \ + \ + definition \ + copy_constructor(copy_constructor &&) = default; \ + ~copy_constructor() = default; \ + copy_constructor &operator=(const copy_constructor &) = default; \ + copy_constructor &operator=(copy_constructor &&) = default; \ + } -MPARK_VARIANT_COPY_CONSTRUCTOR( - Trait::TriviallyAvailable, - copy_constructor(const copy_constructor &that) = default;); + MPARK_VARIANT_COPY_CONSTRUCTOR( + Trait::TriviallyAvailable, + copy_constructor(const copy_constructor &that) = default;); -MPARK_VARIANT_COPY_CONSTRUCTOR( - Trait::Available, copy_constructor(const copy_constructor &that) - : copy_constructor(valueless_t{}) { - this->generic_construct(*this, that); - }); + MPARK_VARIANT_COPY_CONSTRUCTOR( + Trait::Available, + copy_constructor(const copy_constructor &that) + : copy_constructor(valueless_t{}) { + this->generic_construct(*this, that); + }); -MPARK_VARIANT_COPY_CONSTRUCTOR( - Trait::Unavailable, copy_constructor(const copy_constructor &) = delete;); + MPARK_VARIANT_COPY_CONSTRUCTOR( + Trait::Unavailable, + copy_constructor(const copy_constructor &) = delete;); #undef MPARK_VARIANT_COPY_CONSTRUCTOR -template -class assignment : public copy_constructor { - using super = copy_constructor; + template + class assignment : public copy_constructor { + using super = copy_constructor; -public: - MPARK_INHERITING_CTOR(assignment, super) - using super::operator=; + public: + MPARK_INHERITING_CTOR(assignment, super) + using super::operator=; - template - inline /* auto & */ auto emplace(Args &&...args) - -> decltype(this->construct_alt(access::base::get_alt(*this), - lib::forward(args)...)) - { + template + inline /* auto & */ auto emplace(Args &&... args) + -> decltype(this->construct_alt(access::base::get_alt(*this), + lib::forward(args)...)) { this->destroy(); auto &result = this->construct_alt(access::base::get_alt(*this), lib::forward(args)...); this->index_ = I; return result; - } + } -protected: + protected: #ifndef MPARK_GENERIC_LAMBDAS - template - struct assigner { - template - inline void operator()(ThisAlt &this_alt, ThatAlt &&that_alt) const - { - self->assign_alt(this_alt, lib::forward(that_alt).value); + template + struct assigner { + template + inline void operator()(ThisAlt &this_alt, ThatAlt &&that_alt) const { + self->assign_alt(this_alt, lib::forward(that_alt).value); } - assignment *self; - }; + }; #endif - template - inline void assign_alt(alt &a, Arg &&arg) - { + template + inline void assign_alt(alt &a, Arg &&arg) { if (this->index() == I) { #ifdef _MSC_VER #pragma warning(push) #pragma warning(disable : 4244) #endif - a.value = lib::forward(arg); + a.value = lib::forward(arg); #ifdef _MSC_VER #pragma warning(pop) #endif } else { - struct { - void operator()(std::true_type) const - { - this_->emplace(lib::forward(arg_)); - } - - void operator()(std::false_type) const - { - this_->emplace(T(lib::forward(arg_))); - } - - assignment *this_; - Arg &&arg_; - } impl{this, lib::forward(arg)}; - - impl(lib::bool_constant - < std::is_nothrow_constructible::value - || !std::is_nothrow_move_constructible::value > {}); + struct { + void operator()(std::true_type) const { + this_->emplace(lib::forward(arg_)); + } + void operator()(std::false_type) const { + this_->emplace(T(lib::forward(arg_))); + } + assignment *this_; + Arg &&arg_; + } impl{this, lib::forward(arg)}; + impl(lib::bool_constant< + std::is_nothrow_constructible::value || + !std::is_nothrow_move_constructible::value>{}); } - } + } - template - inline void generic_assign(That &&that) - { + template + inline void generic_assign(That &&that) { if (this->valueless_by_exception() && that.valueless_by_exception()) { - // do nothing. + // do nothing. } else if (that.valueless_by_exception()) { - this->destroy(); + this->destroy(); } else { - visitation::alt::visit_alt_at( - that.index(), + visitation::alt::visit_alt_at( + that.index(), #ifdef MPARK_GENERIC_LAMBDAS - [this](auto &this_alt, auto &&that_alt) { - this->assign_alt( - this_alt, - lib::forward(that_alt).value); - } + [this](auto &this_alt, auto &&that_alt) { + this->assign_alt( + this_alt, lib::forward(that_alt).value); + } #else - assigner{this} + assigner{this} #endif - , - *this, lib::forward(that)); + , + *this, + lib::forward(that)); } - } -}; + } + }; -template -class move_assignment; + template + class move_assignment; -#define MPARK_VARIANT_MOVE_ASSIGNMENT(move_assignable_trait, definition) \ - template \ - class move_assignment, move_assignable_trait> \ - : public assignment> { \ - using super = assignment>; \ - \ - public: \ - MPARK_INHERITING_CTOR(move_assignment, super) \ - using super::operator=; \ - \ - move_assignment(const move_assignment &) = default; \ - move_assignment(move_assignment &&) = default; \ - ~move_assignment() = default; \ - move_assignment &operator=(const move_assignment &) = default; \ - definition \ - } +#define MPARK_VARIANT_MOVE_ASSIGNMENT(move_assignable_trait, definition) \ + template \ + class move_assignment, move_assignable_trait> \ + : public assignment> { \ + using super = assignment>; \ + \ + public: \ + MPARK_INHERITING_CTOR(move_assignment, super) \ + using super::operator=; \ + \ + move_assignment(const move_assignment &) = default; \ + move_assignment(move_assignment &&) = default; \ + ~move_assignment() = default; \ + move_assignment &operator=(const move_assignment &) = default; \ + definition \ + } -MPARK_VARIANT_MOVE_ASSIGNMENT( - Trait::TriviallyAvailable, - move_assignment &operator=(move_assignment &&that) = default;); + MPARK_VARIANT_MOVE_ASSIGNMENT( + Trait::TriviallyAvailable, + move_assignment &operator=(move_assignment &&that) = default;); -MPARK_VARIANT_MOVE_ASSIGNMENT( - Trait::Available, - move_assignment & - operator=(move_assignment &&that) noexcept( - lib::all<(std::is_nothrow_move_constructible::value - && std::is_nothrow_move_assignable::value)...>::value) { - this->generic_assign(lib::move(that)); - return *this; - }); + MPARK_VARIANT_MOVE_ASSIGNMENT( + Trait::Available, + move_assignment & + operator=(move_assignment &&that) noexcept( + lib::all<(std::is_nothrow_move_constructible::value && + std::is_nothrow_move_assignable::value)...>::value) { + this->generic_assign(lib::move(that)); + return *this; + }); -MPARK_VARIANT_MOVE_ASSIGNMENT( - Trait::Unavailable, - move_assignment &operator=(move_assignment &&) = delete;); + MPARK_VARIANT_MOVE_ASSIGNMENT( + Trait::Unavailable, + move_assignment &operator=(move_assignment &&) = delete;); #undef MPARK_VARIANT_MOVE_ASSIGNMENT -template -class copy_assignment; + template + class copy_assignment; -#define MPARK_VARIANT_COPY_ASSIGNMENT(copy_assignable_trait, definition) \ - template \ - class copy_assignment, copy_assignable_trait> \ - : public move_assignment> { \ - using super = move_assignment>; \ - \ - public: \ - MPARK_INHERITING_CTOR(copy_assignment, super) \ - using super::operator=; \ - \ - copy_assignment(const copy_assignment &) = default; \ - copy_assignment(copy_assignment &&) = default; \ - ~copy_assignment() = default; \ - definition copy_assignment &operator=(copy_assignment &&) = default; \ - } +#define MPARK_VARIANT_COPY_ASSIGNMENT(copy_assignable_trait, definition) \ + template \ + class copy_assignment, copy_assignable_trait> \ + : public move_assignment> { \ + using super = move_assignment>; \ + \ + public: \ + MPARK_INHERITING_CTOR(copy_assignment, super) \ + using super::operator=; \ + \ + copy_assignment(const copy_assignment &) = default; \ + copy_assignment(copy_assignment &&) = default; \ + ~copy_assignment() = default; \ + definition \ + copy_assignment &operator=(copy_assignment &&) = default; \ + } -MPARK_VARIANT_COPY_ASSIGNMENT( - Trait::TriviallyAvailable, - copy_assignment &operator=(const copy_assignment &that) = default;); + MPARK_VARIANT_COPY_ASSIGNMENT( + Trait::TriviallyAvailable, + copy_assignment &operator=(const copy_assignment &that) = default;); -MPARK_VARIANT_COPY_ASSIGNMENT( - Trait::Available, - copy_assignment & - operator=(const copy_assignment &that) { - this->generic_assign(that); - return *this; - }); + MPARK_VARIANT_COPY_ASSIGNMENT( + Trait::Available, + copy_assignment &operator=(const copy_assignment &that) { + this->generic_assign(that); + return *this; + }); -MPARK_VARIANT_COPY_ASSIGNMENT( - Trait::Unavailable, - copy_assignment &operator=(const copy_assignment &) = delete;); + MPARK_VARIANT_COPY_ASSIGNMENT( + Trait::Unavailable, + copy_assignment &operator=(const copy_assignment &) = delete;); #undef MPARK_VARIANT_COPY_ASSIGNMENT -template -class impl : public copy_assignment> { - using super = copy_assignment>; + template + class impl : public copy_assignment> { + using super = copy_assignment>; -public: - MPARK_INHERITING_CTOR(impl, super) - using super::operator=; + public: + MPARK_INHERITING_CTOR(impl, super) + using super::operator=; - template - inline void assign(Arg &&arg) - { + template + inline void assign(Arg &&arg) { this->assign_alt(access::base::get_alt(*this), lib::forward(arg)); - } + } - inline void swap(impl &that) - { + inline void swap(impl &that) { if (this->valueless_by_exception() && that.valueless_by_exception()) { - // do nothing. + // do nothing. } else if (this->index() == that.index()) { - visitation::alt::visit_alt_at( - this->index(), + visitation::alt::visit_alt_at(this->index(), #ifdef MPARK_GENERIC_LAMBDAS - [](auto &this_alt, auto &that_alt) { - using std::swap; - swap(this_alt.value, that_alt.value); - } + [](auto &this_alt, auto &that_alt) { + using std::swap; + swap(this_alt.value, + that_alt.value); + } #else - swapper{} + swapper{} #endif - , - *this, that); + , + *this, + that); } else { - impl *lhs = this; - impl *rhs = lib::addressof(that); - if (lhs->move_nothrow() && !rhs->move_nothrow()) { - std::swap(lhs, rhs); - } - impl tmp(lib::move(*rhs)); + impl *lhs = this; + impl *rhs = lib::addressof(that); + if (lhs->move_nothrow() && !rhs->move_nothrow()) { + std::swap(lhs, rhs); + } + impl tmp(lib::move(*rhs)); #ifdef MPARK_EXCEPTIONS - // EXTENSION: When the move construction of `lhs` into `rhs` throws - // and `tmp` is nothrow move constructible then we move `tmp` back - // into `rhs` and provide the strong exception safety guarantee. - try { - this->generic_construct(*rhs, lib::move(*lhs)); - } catch (...) { - if (tmp.move_nothrow()) { - this->generic_construct(*rhs, lib::move(tmp)); - } - throw; - } -#else + // EXTENSION: When the move construction of `lhs` into `rhs` throws + // and `tmp` is nothrow move constructible then we move `tmp` back + // into `rhs` and provide the strong exception safety guarantee. + try { this->generic_construct(*rhs, lib::move(*lhs)); + } catch (...) { + if (tmp.move_nothrow()) { + this->generic_construct(*rhs, lib::move(tmp)); + } + throw; + } +#else + this->generic_construct(*rhs, lib::move(*lhs)); #endif - this->generic_construct(*lhs, lib::move(tmp)); + this->generic_construct(*lhs, lib::move(tmp)); } - } + } -private: + private: #ifndef MPARK_GENERIC_LAMBDAS - struct swapper { - template - inline void operator()(ThisAlt &this_alt, ThatAlt &that_alt) const - { - using std::swap; - swap(this_alt.value, that_alt.value); + struct swapper { + template + inline void operator()(ThisAlt &this_alt, ThatAlt &that_alt) const { + using std::swap; + swap(this_alt.value, that_alt.value); } - }; + }; #endif - inline constexpr bool move_nothrow() const - { - return this->valueless_by_exception() - || lib::array{ - {std::is_nothrow_move_constructible< - Ts>::value...}}[this->index()]; - } -}; + inline constexpr bool move_nothrow() const { + return this->valueless_by_exception() || + lib::array{ + {std::is_nothrow_move_constructible::value...} + }[this->index()]; + } + }; #undef MPARK_INHERITING_CTOR -template -struct overload_leaf { - using F = lib::size_constant (*)(T); + template + struct overload_leaf { + using F = lib::size_constant (*)(T); + operator F() const { return nullptr; } + }; - operator F() const { return nullptr; } -}; + template + struct overload_impl { + private: + template + struct impl; -template -struct overload_impl { -private: - template - struct impl; + template + struct impl> : overload_leaf... {}; - template - struct impl> : overload_leaf... {}; + public: + using type = impl>; + }; -public: - using type = impl>; -}; + template + using overload = typename overload_impl::type; -template -using overload = typename overload_impl::type; + template + using best_match = lib::invoke_result_t, T &&>; -template -using best_match = lib::invoke_result_t, T &&>; + template + struct is_in_place_index : std::false_type {}; -template -struct is_in_place_index : std::false_type {}; + template + struct is_in_place_index> : std::true_type {}; -template -struct is_in_place_index> : std::true_type {}; + template + struct is_in_place_type : std::false_type {}; -template -struct is_in_place_type : std::false_type {}; + template + struct is_in_place_type> : std::true_type {}; -template -struct is_in_place_type> : std::true_type {}; + } // detail -}// namespace detail - -template -class variant { + template + class variant { static_assert(0 < sizeof...(Ts), "variant must consist of at least one alternative."); @@ -2378,19 +2220,18 @@ class variant { static_assert(lib::all::value...>::value, "variant can not have a void type as an alternative."); -public: - template< + public: + template < typename Front = lib::type_pack_element_t<0, Ts...>, lib::enable_if_t::value, int> = 0> inline constexpr variant() noexcept( std::is_nothrow_default_constructible::value) - : impl_(in_place_index_t<0>{}) - {} + : impl_(in_place_index_t<0>{}) {} variant(const variant &) = default; variant(variant &&) = default; - template< + template < typename Arg, typename Decayed = lib::decay_t, lib::enable_if_t::value, int> = 0, @@ -2401,318 +2242,285 @@ public: lib::enable_if_t::value, int> = 0> inline constexpr variant(Arg &&arg) noexcept( std::is_nothrow_constructible::value) - : impl_(in_place_index_t{}, lib::forward(arg)) - {} + : impl_(in_place_index_t{}, lib::forward(arg)) {} - template< + template < std::size_t I, typename... Args, typename T = lib::type_pack_element_t, lib::enable_if_t::value, int> = 0> inline explicit constexpr variant( in_place_index_t, - Args &&...args) noexcept(std::is_nothrow_constructible::value) - : impl_(in_place_index_t{}, lib::forward(args)...) - {} + Args &&... args) noexcept(std::is_nothrow_constructible::value) + : impl_(in_place_index_t{}, lib::forward(args)...) {} - template, - lib::enable_if_t &, - Args...>::value, - int> = 0> + template < + std::size_t I, + typename Up, + typename... Args, + typename T = lib::type_pack_element_t, + lib::enable_if_t &, + Args...>::value, + int> = 0> inline explicit constexpr variant( in_place_index_t, std::initializer_list il, - Args &&...args) noexcept(std:: - is_nothrow_constructible< - T, - std::initializer_list &, - Args...>::value) - : impl_(in_place_index_t{}, il, lib::forward(args)...) - {} + Args &&... args) noexcept(std:: + is_nothrow_constructible< + T, + std::initializer_list &, + Args...>::value) + : impl_(in_place_index_t{}, il, lib::forward(args)...) {} - template< + template < typename T, typename... Args, std::size_t I = detail::find_index_sfinae::value, lib::enable_if_t::value, int> = 0> inline explicit constexpr variant( in_place_type_t, - Args &&...args) noexcept(std::is_nothrow_constructible::value) - : impl_(in_place_index_t{}, lib::forward(args)...) - {} + Args &&... args) noexcept(std::is_nothrow_constructible::value) + : impl_(in_place_index_t{}, lib::forward(args)...) {} - template::value, - lib::enable_if_t &, - Args...>::value, - int> = 0> + template < + typename T, + typename Up, + typename... Args, + std::size_t I = detail::find_index_sfinae::value, + lib::enable_if_t &, + Args...>::value, + int> = 0> inline explicit constexpr variant( in_place_type_t, std::initializer_list il, - Args &&...args) noexcept(std:: - is_nothrow_constructible< - T, - std::initializer_list &, - Args...>::value) - : impl_(in_place_index_t{}, il, lib::forward(args)...) - {} + Args &&... args) noexcept(std:: + is_nothrow_constructible< + T, + std::initializer_list &, + Args...>::value) + : impl_(in_place_index_t{}, il, lib::forward(args)...) {} ~variant() = default; variant &operator=(const variant &) = default; variant &operator=(variant &&) = default; - template, variant>::value, - int> = 0, - std::size_t I = detail::best_match::value, - typename T = lib::type_pack_element_t, - lib::enable_if_t<(std::is_assignable::value - && std::is_constructible::value), - int> = 0> + template , variant>::value, + int> = 0, + std::size_t I = detail::best_match::value, + typename T = lib::type_pack_element_t, + lib::enable_if_t<(std::is_assignable::value && + std::is_constructible::value), + int> = 0> inline variant &operator=(Arg &&arg) noexcept( - (std::is_nothrow_assignable::value - && std::is_nothrow_constructible::value)) - { - impl_.template assign(lib::forward(arg)); - return *this; + (std::is_nothrow_assignable::value && + std::is_nothrow_constructible::value)) { + impl_.template assign(lib::forward(arg)); + return *this; } - template< + template < std::size_t I, typename... Args, typename T = lib::type_pack_element_t, lib::enable_if_t::value, int> = 0> - inline T &emplace(Args &&...args) - { - return impl_.template emplace(lib::forward(args)...); + inline T &emplace(Args &&... args) { + return impl_.template emplace(lib::forward(args)...); } - template, - lib::enable_if_t &, - Args...>::value, - int> = 0> - inline T &emplace(std::initializer_list il, Args &&...args) - { - return impl_.template emplace(il, lib::forward(args)...); + template < + std::size_t I, + typename Up, + typename... Args, + typename T = lib::type_pack_element_t, + lib::enable_if_t &, + Args...>::value, + int> = 0> + inline T &emplace(std::initializer_list il, Args &&... args) { + return impl_.template emplace(il, lib::forward(args)...); } - template< + template < typename T, typename... Args, std::size_t I = detail::find_index_sfinae::value, lib::enable_if_t::value, int> = 0> - inline T &emplace(Args &&...args) - { - return impl_.template emplace(lib::forward(args)...); + inline T &emplace(Args &&... args) { + return impl_.template emplace(lib::forward(args)...); } - template::value, - lib::enable_if_t &, - Args...>::value, - int> = 0> - inline T &emplace(std::initializer_list il, Args &&...args) - { - return impl_.template emplace(il, lib::forward(args)...); + template < + typename T, + typename Up, + typename... Args, + std::size_t I = detail::find_index_sfinae::value, + lib::enable_if_t &, + Args...>::value, + int> = 0> + inline T &emplace(std::initializer_list il, Args &&... args) { + return impl_.template emplace(il, lib::forward(args)...); } - inline constexpr bool valueless_by_exception() const noexcept - { - return impl_.valueless_by_exception(); + inline constexpr bool valueless_by_exception() const noexcept { + return impl_.valueless_by_exception(); } - inline constexpr std::size_t index() const noexcept - { - return impl_.index(); + inline constexpr std::size_t index() const noexcept { + return impl_.index(); } - template, - Dummy>::value - && lib::dependent_type, - Dummy>::value)...>::value, - int> = 0> + template , + Dummy>::value && + lib::dependent_type, + Dummy>::value)...>::value, + int> = 0> inline void swap(variant &that) noexcept( - lib::all<(std::is_nothrow_move_constructible::value - && lib::is_nothrow_swappable::value)...>::value) - { - impl_.swap(that.impl_); + lib::all<(std::is_nothrow_move_constructible::value && + lib::is_nothrow_swappable::value)...>::value) { + impl_.swap(that.impl_); } -private: + private: detail::impl impl_; friend struct detail::access::variant; friend struct detail::visitation::variant; -}; + }; -template -inline constexpr bool -holds_alternative(const variant &v) noexcept -{ + template + inline constexpr bool holds_alternative(const variant &v) noexcept { return v.index() == I; -} + } -template -inline constexpr bool -holds_alternative(const variant &v) noexcept -{ + template + inline constexpr bool holds_alternative(const variant &v) noexcept { return holds_alternative::value>(v); -} + } -namespace detail { -template -struct generic_get_impl { - constexpr generic_get_impl(int) noexcept {} + namespace detail { + template + struct generic_get_impl { + constexpr generic_get_impl(int) noexcept {} - constexpr AUTO_REFREF operator()(V &&v) const AUTO_REFREF_RETURN( - access::variant::get_alt(lib::forward(v)).value) -}; + constexpr AUTO_REFREF operator()(V &&v) const + AUTO_REFREF_RETURN( + access::variant::get_alt(lib::forward(v)).value) + }; -template -inline constexpr AUTO_REFREF -generic_get(V &&v) - AUTO_REFREF_RETURN(generic_get_impl(holds_alternative(v) - ? 0 - : (throw_bad_variant_access(), - 0))(lib::forward(v))) -}// namespace detail + template + inline constexpr AUTO_REFREF generic_get(V &&v) + AUTO_REFREF_RETURN(generic_get_impl( + holds_alternative(v) ? 0 : (throw_bad_variant_access(), 0))( + lib::forward(v))) + } // namespace detail -template -inline constexpr variant_alternative_t> & -get(variant &v) -{ + template + inline constexpr variant_alternative_t> &get( + variant &v) { return detail::generic_get(v); -} + } -template -inline constexpr variant_alternative_t> && -get(variant &&v) -{ + template + inline constexpr variant_alternative_t> &&get( + variant &&v) { return detail::generic_get(lib::move(v)); -} + } -template -inline constexpr const variant_alternative_t> & -get(const variant &v) -{ + template + inline constexpr const variant_alternative_t> &get( + const variant &v) { return detail::generic_get(v); -} + } -template -inline constexpr const variant_alternative_t> && -get(const variant &&v) -{ + template + inline constexpr const variant_alternative_t> &&get( + const variant &&v) { return detail::generic_get(lib::move(v)); -} + } -template -inline constexpr T & -get(variant &v) -{ + template + inline constexpr T &get(variant &v) { return get::value>(v); -} + } -template -inline constexpr T && -get(variant &&v) -{ + template + inline constexpr T &&get(variant &&v) { return get::value>(lib::move(v)); -} + } -template -inline constexpr const T & -get(const variant &v) -{ + template + inline constexpr const T &get(const variant &v) { return get::value>(v); -} + } -template -inline constexpr const T && -get(const variant &&v) -{ + template + inline constexpr const T &&get(const variant &&v) { return get::value>(lib::move(v)); -} + } -namespace detail { + namespace detail { -template -inline constexpr /* auto * */ AUTO -generic_get_if(V *v) noexcept - AUTO_RETURN(v &&holds_alternative(*v) - ? lib::addressof(access::variant::get_alt(*v).value) - : nullptr) + template + inline constexpr /* auto * */ AUTO generic_get_if(V *v) noexcept + AUTO_RETURN(v && holds_alternative(*v) + ? lib::addressof(access::variant::get_alt(*v).value) + : nullptr) -}// namespace detail + } // namespace detail -template -inline constexpr lib::add_pointer_t>> -get_if(variant *v) noexcept -{ + template + inline constexpr lib::add_pointer_t>> + get_if(variant *v) noexcept { return detail::generic_get_if(v); -} + } -template -inline constexpr lib::add_pointer_t< - const variant_alternative_t>> -get_if(const variant *v) noexcept -{ + template + inline constexpr lib::add_pointer_t< + const variant_alternative_t>> + get_if(const variant *v) noexcept { return detail::generic_get_if(v); -} + } -template -inline constexpr lib::add_pointer_t -get_if(variant *v) noexcept -{ + template + inline constexpr lib::add_pointer_t + get_if(variant *v) noexcept { return get_if::value>(v); -} + } -template -inline constexpr lib::add_pointer_t -get_if(const variant *v) noexcept -{ + template + inline constexpr lib::add_pointer_t + get_if(const variant *v) noexcept { return get_if::value>(v); -} + } -namespace detail { -template -struct convert_to_bool { - template - inline constexpr bool operator()(Lhs &&lhs, Rhs &&rhs) const - { + namespace detail { + template + struct convert_to_bool { + template + inline constexpr bool operator()(Lhs &&lhs, Rhs &&rhs) const { static_assert(std::is_convertible, bool>::value, "relational operators must return a type" " implicitly convertible to bool"); - return lib::invoke(RelOp{}, lib::forward(lhs), - lib::forward(rhs)); - } -}; -}// namespace detail + return lib::invoke( + RelOp{}, lib::forward(lhs), lib::forward(rhs)); + } + }; + } // namespace detail -template -inline constexpr bool -operator==(const variant &lhs, const variant &rhs) -{ + template + inline constexpr bool operator==(const variant &lhs, + const variant &rhs) { using detail::visitation::variant; using equal_to = detail::convert_to_bool; #ifdef MPARK_CPP14_CONSTEXPR @@ -2720,16 +2528,15 @@ operator==(const variant &lhs, const variant &rhs) if (lhs.valueless_by_exception()) return true; return variant::visit_value_at(lhs.index(), equal_to{}, lhs, rhs); #else - return lhs.index() == rhs.index() - && (lhs.valueless_by_exception() - || variant::visit_value_at(lhs.index(), equal_to{}, lhs, rhs)); + return lhs.index() == rhs.index() && + (lhs.valueless_by_exception() || + variant::visit_value_at(lhs.index(), equal_to{}, lhs, rhs)); #endif -} + } -template -inline constexpr bool -operator!=(const variant &lhs, const variant &rhs) -{ + template + inline constexpr bool operator!=(const variant &lhs, + const variant &rhs) { using detail::visitation::variant; using not_equal_to = detail::convert_to_bool; #ifdef MPARK_CPP14_CONSTEXPR @@ -2737,16 +2544,15 @@ operator!=(const variant &lhs, const variant &rhs) if (lhs.valueless_by_exception()) return false; return variant::visit_value_at(lhs.index(), not_equal_to{}, lhs, rhs); #else - return lhs.index() != rhs.index() - || (!lhs.valueless_by_exception() - && variant::visit_value_at(lhs.index(), not_equal_to{}, lhs, rhs)); + return lhs.index() != rhs.index() || + (!lhs.valueless_by_exception() && + variant::visit_value_at(lhs.index(), not_equal_to{}, lhs, rhs)); #endif -} + } -template -inline constexpr bool -operator<(const variant &lhs, const variant &rhs) -{ + template + inline constexpr bool operator<(const variant &lhs, + const variant &rhs) { using detail::visitation::variant; using less = detail::convert_to_bool; #ifdef MPARK_CPP14_CONSTEXPR @@ -2756,17 +2562,16 @@ operator<(const variant &lhs, const variant &rhs) if (lhs.index() > rhs.index()) return false; return variant::visit_value_at(lhs.index(), less{}, lhs, rhs); #else - return !rhs.valueless_by_exception() - && (lhs.valueless_by_exception() || lhs.index() < rhs.index() - || (lhs.index() == rhs.index() - && variant::visit_value_at(lhs.index(), less{}, lhs, rhs))); + return !rhs.valueless_by_exception() && + (lhs.valueless_by_exception() || lhs.index() < rhs.index() || + (lhs.index() == rhs.index() && + variant::visit_value_at(lhs.index(), less{}, lhs, rhs))); #endif -} + } -template -inline constexpr bool -operator>(const variant &lhs, const variant &rhs) -{ + template + inline constexpr bool operator>(const variant &lhs, + const variant &rhs) { using detail::visitation::variant; using greater = detail::convert_to_bool; #ifdef MPARK_CPP14_CONSTEXPR @@ -2776,17 +2581,16 @@ operator>(const variant &lhs, const variant &rhs) if (lhs.index() < rhs.index()) return false; return variant::visit_value_at(lhs.index(), greater{}, lhs, rhs); #else - return !lhs.valueless_by_exception() - && (rhs.valueless_by_exception() || lhs.index() > rhs.index() - || (lhs.index() == rhs.index() - && variant::visit_value_at(lhs.index(), greater{}, lhs, rhs))); + return !lhs.valueless_by_exception() && + (rhs.valueless_by_exception() || lhs.index() > rhs.index() || + (lhs.index() == rhs.index() && + variant::visit_value_at(lhs.index(), greater{}, lhs, rhs))); #endif -} + } -template -inline constexpr bool -operator<=(const variant &lhs, const variant &rhs) -{ + template + inline constexpr bool operator<=(const variant &lhs, + const variant &rhs) { using detail::visitation::variant; using less_equal = detail::convert_to_bool; #ifdef MPARK_CPP14_CONSTEXPR @@ -2796,19 +2600,17 @@ operator<=(const variant &lhs, const variant &rhs) if (lhs.index() > rhs.index()) return false; return variant::visit_value_at(lhs.index(), less_equal{}, lhs, rhs); #else - return lhs.valueless_by_exception() - || (!rhs.valueless_by_exception() - && (lhs.index() < rhs.index() - || (lhs.index() == rhs.index() - && variant::visit_value_at(lhs.index(), less_equal{}, lhs, - rhs)))); + return lhs.valueless_by_exception() || + (!rhs.valueless_by_exception() && + (lhs.index() < rhs.index() || + (lhs.index() == rhs.index() && + variant::visit_value_at(lhs.index(), less_equal{}, lhs, rhs)))); #endif -} + } -template -inline constexpr bool -operator>=(const variant &lhs, const variant &rhs) -{ + template + inline constexpr bool operator>=(const variant &lhs, + const variant &rhs) { using detail::visitation::variant; using greater_equal = detail::convert_to_bool; #ifdef MPARK_CPP14_CONSTEXPR @@ -2818,144 +2620,123 @@ operator>=(const variant &lhs, const variant &rhs) if (lhs.index() < rhs.index()) return false; return variant::visit_value_at(lhs.index(), greater_equal{}, lhs, rhs); #else - return rhs.valueless_by_exception() - || (!lhs.valueless_by_exception() - && (lhs.index() > rhs.index() - || (lhs.index() == rhs.index() - && variant::visit_value_at(lhs.index(), greater_equal{}, - lhs, rhs)))); + return rhs.valueless_by_exception() || + (!lhs.valueless_by_exception() && + (lhs.index() > rhs.index() || + (lhs.index() == rhs.index() && + variant::visit_value_at( + lhs.index(), greater_equal{}, lhs, rhs)))); #endif -} + } -struct monostate {}; + struct monostate {}; -inline constexpr bool -operator<(monostate, monostate) noexcept -{ + inline constexpr bool operator<(monostate, monostate) noexcept { return false; -} + } -inline constexpr bool -operator>(monostate, monostate) noexcept -{ + inline constexpr bool operator>(monostate, monostate) noexcept { return false; -} + } -inline constexpr bool -operator<=(monostate, monostate) noexcept -{ + inline constexpr bool operator<=(monostate, monostate) noexcept { return true; -} + } -inline constexpr bool -operator>=(monostate, monostate) noexcept -{ + inline constexpr bool operator>=(monostate, monostate) noexcept { return true; -} + } -inline constexpr bool -operator==(monostate, monostate) noexcept -{ + inline constexpr bool operator==(monostate, monostate) noexcept { return true; -} + } -inline constexpr bool -operator!=(monostate, monostate) noexcept -{ + inline constexpr bool operator!=(monostate, monostate) noexcept { return false; -} + } #ifdef MPARK_CPP14_CONSTEXPR -namespace detail { + namespace detail { -inline constexpr bool -all(std::initializer_list bs) -{ - for (bool b : bs) { - if (!b) { return false; } + inline constexpr bool all(std::initializer_list bs) { + for (bool b : bs) { + if (!b) { + return false; + } + } + return true; } - return true; -} -}// namespace detail + } // namespace detail -template -inline constexpr decltype(auto) -visit(Visitor &&visitor, Vs &&...vs) -{ + template + inline constexpr decltype(auto) visit(Visitor &&visitor, Vs &&... vs) { return (detail::all({!vs.valueless_by_exception()...}) - ? (void) 0 + ? (void)0 : throw_bad_variant_access()), detail::visitation::variant::visit_value( lib::forward(visitor), lib::forward(vs)...); -} + } #else -namespace detail { + namespace detail { -template -inline constexpr bool -all_impl(const lib::array &bs, std::size_t idx) -{ - return idx >= N || (bs[idx] && all_impl(bs, idx + 1)); -} + template + inline constexpr bool all_impl(const lib::array &bs, + std::size_t idx) { + return idx >= N || (bs[idx] && all_impl(bs, idx + 1)); + } -template -inline constexpr bool -all(const lib::array &bs) -{ - return all_impl(bs, 0); -} + template + inline constexpr bool all(const lib::array &bs) { + return all_impl(bs, 0); + } -}// namespace detail + } // namespace detail -template -inline constexpr DECLTYPE_AUTO -visit(Visitor &&visitor, Vs &&...vs) DECLTYPE_AUTO_RETURN( - (detail::all(lib::array{ - {!vs.valueless_by_exception()...}}) - ? (void) 0 - : throw_bad_variant_access()), - detail::visitation::variant::visit_value(lib::forward(visitor), - lib::forward(vs)...)) + template + inline constexpr DECLTYPE_AUTO visit(Visitor &&visitor, Vs &&... vs) + DECLTYPE_AUTO_RETURN( + (detail::all( + lib::array{{!vs.valueless_by_exception()...}}) + ? (void)0 + : throw_bad_variant_access()), + detail::visitation::variant::visit_value(lib::forward(visitor), + lib::forward(vs)...)) #endif -template -inline auto -swap(variant &lhs, variant &rhs) noexcept(noexcept(lhs.swap(rhs))) - -> decltype(lhs.swap(rhs)) -{ + template + inline auto swap(variant &lhs, + variant &rhs) noexcept(noexcept(lhs.swap(rhs))) + -> decltype(lhs.swap(rhs)) { lhs.swap(rhs); -} + } -namespace detail { + namespace detail { -template -using enabled_type = T; + template + using enabled_type = T; -namespace hash { + namespace hash { -template -constexpr bool -meets_requirements() noexcept -{ - return std::is_copy_constructible::value - && std::is_move_constructible::value - && lib::is_invocable_r::value; -} + template + constexpr bool meets_requirements() noexcept { + return std::is_copy_constructible::value && + std::is_move_constructible::value && + lib::is_invocable_r::value; + } -template -constexpr bool -is_enabled() noexcept -{ - using H = std::hash; - return meets_requirements() && std::is_default_constructible::value - && std::is_copy_assignable::value - && std::is_move_assignable::value; -} + template + constexpr bool is_enabled() noexcept { + using H = std::hash; + return meets_requirements() && + std::is_default_constructible::value && + std::is_copy_assignable::value && + std::is_move_assignable::value; + } -}// namespace hash + } // namespace hash -}// namespace detail + } // namespace detail #undef AUTO #undef AUTO_RETURN @@ -2966,77 +2747,67 @@ is_enabled() noexcept #undef DECLTYPE_AUTO #undef DECLTYPE_AUTO_RETURN -}// namespace mpark +} // namespace mpark namespace std { -template -struct hash, - mpark::lib::enable_if_t>()...>::value>>> { + template + struct hash, + mpark::lib::enable_if_t>()...>::value>>> { using argument_type = mpark::variant; using result_type = std::size_t; - inline result_type operator()(const argument_type &v) const - { - using mpark::detail::visitation::variant; - std::size_t result = v.valueless_by_exception() - ? 299792458// Random value chosen by the universe upon creation - : variant::visit_alt( + inline result_type operator()(const argument_type &v) const { + using mpark::detail::visitation::variant; + std::size_t result = + v.valueless_by_exception() + ? 299792458 // Random value chosen by the universe upon creation + : variant::visit_alt( #ifdef MPARK_GENERIC_LAMBDAS - [](const auto &alt) { - using alt_type = mpark::lib::decay_t; - using value_type = mpark::lib::remove_const_t< - typename alt_type::value_type>; - return hash{}(alt.value); - } + [](const auto &alt) { + using alt_type = mpark::lib::decay_t; + using value_type = mpark::lib::remove_const_t< + typename alt_type::value_type>; + return hash{}(alt.value); + } #else - hasher{} + hasher{} #endif - , - v); - return hash_combine(result, hash{}(v.index())); + , + v); + return hash_combine(result, hash{}(v.index())); } -private: + private: #ifndef MPARK_GENERIC_LAMBDAS struct hasher { - template - inline std::size_t operator()(const Alt &alt) const - { - using alt_type = mpark::lib::decay_t; - using value_type = - mpark::lib::remove_const_t; - return hash{}(alt.value); - } + template + inline std::size_t operator()(const Alt &alt) const { + using alt_type = mpark::lib::decay_t; + using value_type = + mpark::lib::remove_const_t; + return hash{}(alt.value); + } }; #endif - static std::size_t hash_combine(std::size_t lhs, std::size_t rhs) - { - return lhs ^= rhs + 0x9e3779b9 + (lhs << 6) + (lhs >> 2); + static std::size_t hash_combine(std::size_t lhs, std::size_t rhs) { + return lhs ^= rhs + 0x9e3779b9 + (lhs << 6) + (lhs >> 2); } -}; + }; -template<> -struct hash { + template <> + struct hash { using argument_type = mpark::monostate; using result_type = std::size_t; - inline result_type operator()(const argument_type &) const noexcept - { - return 66740831;// return a fundamentally attractive random value. + inline result_type operator()(const argument_type &) const noexcept { + return 66740831; // return a fundamentally attractive random value. } -}; + }; -}// namespace std +} // namespace std -namespace sled { -// template -// using variant = mpark::variant; -using namespace mpark; - -}// namespace sled - -#endif// SLED_MPARK_VARIANT_HPP +#endif // MPARK_VARIANT_HPP