From 9ee90e0bff6e80c100c34266f177f13b79b5f151 Mon Sep 17 00:00:00 2001 From: Simon Brand Date: Fri, 27 Oct 2017 09:07:56 +0100 Subject: [PATCH] Clang format --- expected.hpp | 1041 ++++++++++++++++++++++++++------------------------ 1 file changed, 548 insertions(+), 493 deletions(-) diff --git a/expected.hpp b/expected.hpp index 9bbdb2f..0d5b131 100644 --- a/expected.hpp +++ b/expected.hpp @@ -14,557 +14,612 @@ #ifndef TL_EXPECTED_HPP #define TL_EXPECTED_HPP +#include #include #include -#include namespace tl { - namespace detail { +namespace detail { template using enable_if_t = typename std::enable_if::type; - } +} - #ifndef TL_IN_PLACE_T_DEFINED - #define TL_IN_PLACE_T_DEFINED - /// \brief A tag type to tell optional to construct its value in-place - struct in_place_t { - explicit in_place_t() = default; - }; - /// \brief A tag to tell optional to construct its value in-place - static constexpr in_place_t in_place{}; - #endif +#ifndef TL_IN_PLACE_T_DEFINED +#define TL_IN_PLACE_T_DEFINED +/// \brief A tag type to tell optional to construct its value in-place +struct in_place_t { + explicit in_place_t() = default; +}; +/// \brief A tag to tell optional to construct its value in-place +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) {} +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)) {} + constexpr explicit unexpected(E &&e) : m_val(std::move(e)) {} - constexpr const E& value() const & { return m_val; } - constexpr E& value() & { return m_val; } - constexpr E&& value() && { return std::move(m_val); } - constexpr E const&& value() const&& { return std::move(m_val); } - private: - E m_val; // exposition only - }; + constexpr const E &value() const & { return m_val; } + constexpr E &value() & { return m_val; } + constexpr E &&value() && { return std::move(m_val); } + constexpr E const &&value() const && { return std::move(m_val); } - 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(); - } +private: + E m_val; +}; - struct unexpect_t { - unexpect_t() = default; - }; - static constexpr unexpect_t unexpect{}; +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(); +} + +struct unexpect_t { + unexpect_t() = default; +}; +static constexpr unexpect_t unexpect{}; namespace detail { - template ::value, bool = std::is_trivially_destructible::value> - struct expected_storage_base { - constexpr expected_storage_base() - : m_val(T{}), m_has_val(true) {} +template ::value, + bool = std::is_trivially_destructible::value> +struct expected_storage_base { + constexpr expected_storage_base() : m_val(T{}), m_has_val(true) {} - template ::value>* = nullptr> - constexpr expected_storage_base(in_place_t, Args&&... args) : - m_val(std::forward(args)...), m_has_val(true) {} + 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 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) {} + 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(); - } - } - bool m_has_val; - union { - T m_val; - unexpected m_unexpect; - }; - }; - - template - struct expected_storage_base { - constexpr expected_storage_base() - : m_val(T{}), m_has_val(true) {} - - - 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; - bool m_has_val; - union { - T m_val; - unexpected m_unexpect; - }; - }; - - template - struct expected_storage_base { - constexpr expected_storage_base() - : m_val(T{}), m_has_val(true) {} - - - 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(); - } - } - - bool m_has_val; - union { - T m_val; - unexpected m_unexpect; - }; - - }; - - template - struct expected_storage_base { - constexpr expected_storage_base() - : m_val(T{}), m_has_val(true) {} - - - 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(); - } - } - bool m_has_val; - union { - T m_val; - unexpected m_unexpect; - }; - }; - - template - struct expected_storage_base { - constexpr expected_storage_base() - : m_val(), 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; - - bool m_has_val; - struct dummy{}; - union { - dummy m_val; - unexpected m_unexpect; - }; - }; - - template - struct expected_storage_base { - constexpr expected_storage_base() - : m_val(), 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(); - } - } - - bool m_has_val; - struct dummy{}; - union { - dummy m_val; - unexpected m_unexpect; - }; - }; - - //TODO, conditionally delete things - template - class expected_ctor_base{}; -} - - -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"; + ~expected_storage_base() { + if (m_has_val) { + m_val.~T(); + } else { + m_unexpect.~unexpected(); } + } + bool m_has_val; + union { + T m_val; + unexpected m_unexpect; + }; +}; + +template struct expected_storage_base { + constexpr expected_storage_base() : m_val(T{}), m_has_val(true) {} + + 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; + bool m_has_val; + union { + T m_val; + unexpected m_unexpect; + }; +}; + +template struct expected_storage_base { + constexpr expected_storage_base() : m_val(T{}), m_has_val(true) {} + + 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(); + } + } + + bool m_has_val; + union { + T m_val; + unexpected m_unexpect; + }; +}; + +template struct expected_storage_base { + constexpr expected_storage_base() : m_val(T{}), m_has_val(true) {} + + 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(); + } + } + bool m_has_val; + union { + T m_val; + unexpected m_unexpect; + }; +}; + +template struct expected_storage_base { + constexpr expected_storage_base() : m_val(), 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; + + bool m_has_val; + struct dummy {}; + union { + dummy m_val; + unexpected m_unexpect; + }; +}; + +template struct expected_storage_base { + constexpr expected_storage_base() : m_val(), 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(); + } + } + + bool m_has_val; + struct dummy {}; + union { + dummy m_val; + unexpected m_unexpect; + }; +}; + +// TODO, conditionally delete things +template class expected_ctor_base {}; +} // 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); } - 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; + E m_val; }; template -class expected : private detail::expected_storage_base, private detail::expected_ctor_base { - static_assert(!std::is_reference::value, "T must not be a reference"); - static_assert(!std::is_same>::value, "T must not be in_place_t"); - static_assert(!std::is_same>::value, "T must not be unexpect_t"); - static_assert(!std::is_same>>::value, "T must not be unexpected"); - static_assert(!std::is_reference::value, "E must not be a reference"); - static_assert(!std::is_same::value, "T must not be void"); +class expected : private detail::expected_storage_base, + private detail::expected_ctor_base { + static_assert(!std::is_reference::value, "T must not be a reference"); + static_assert(!std::is_same>::value, + "T must not be in_place_t"); + static_assert(!std::is_same>::value, + "T must not be unexpect_t"); + static_assert(!std::is_same>>::value, + "T must not be unexpected"); + static_assert(!std::is_reference::value, "E must not be a reference"); + static_assert(!std::is_same::value, "T must not be void"); - T* valptr() { return std::addressof(this->m_val); } - unexpected* errptr() { return std::addressof(this->m_unexpect); } - T& val() { return this->m_val; } - unexpected& err() { return this->m_unexpect; } - const T& val() const { return this->m_val; } - const unexpected& err() const { return this->m_unexpect; } + T *valptr() { return std::addressof(this->m_val); } + unexpected *errptr() { return std::addressof(this->m_unexpect); } + T &val() { return this->m_val; } + unexpected &err() { return this->m_unexpect; } + const T &val() const { return this->m_val; } + const unexpected &err() const { return this->m_unexpect; } - using storage_base = detail::expected_storage_base; + using storage_base = detail::expected_storage_base; public: - typedef T value_type; - typedef E error_type; - typedef unexpected unexpected_type; + typedef T value_type; + typedef E error_type; + typedef unexpected unexpected_type; - constexpr expected() = default; + constexpr expected() = default; - template ::value>* = nullptr> - constexpr expected(in_place_t, Args&&... args) : - storage_base(in_place, std::forward(args)...){} + template ::value> * = + nullptr> + constexpr expected(in_place_t, Args &&... args) + : storage_base(in_place, std::forward(args)...) {} - template &, Args&&...>::value>* = nullptr> - constexpr expected(in_place_t, std::initializer_list il, Args&&... args) : - storage_base(in_place, il, std::forward(args)...){} + template &, Args &&...>::value> * = nullptr> + constexpr expected(in_place_t, std::initializer_list il, Args &&... args) + : storage_base(in_place, il, std::forward(args)...) {} - template ::value>* = nullptr, detail::enable_if_t::value>* = nullptr> - explicit constexpr expected(unexpected const& e) - : storage_base(unexpect, e) {} + template ::value> * = + nullptr, + detail::enable_if_t::value> * = + nullptr> + explicit constexpr expected(unexpected const &e) + : storage_base(unexpect, e) {} - template ::value>* = nullptr, detail::enable_if_t::value>* = nullptr> - constexpr expected(unexpected const& e) - : storage_base(unexpect, e) {} + template < + class G = E, + detail::enable_if_t::value> * = + nullptr, + detail::enable_if_t::value> * = nullptr> + constexpr expected(unexpected const &e) : storage_base(unexpect, e) {} - template ::value>* = nullptr, detail::enable_if_t::value>* = nullptr> - explicit constexpr expected(unexpected && e) noexcept(std::is_nothrow_constructible::value) - : storage_base(unexpect, std::move(e)) {} + template < + class G = E, + detail::enable_if_t::value> * = nullptr, + detail::enable_if_t::value> * = nullptr> + explicit constexpr expected(unexpected &&e) noexcept( + std::is_nothrow_constructible::value) + : storage_base(unexpect, std::move(e)) {} - template ::value>* = nullptr, detail::enable_if_t::value>* = nullptr> - constexpr expected(unexpected && e) noexcept(std::is_nothrow_constructible::value) - : storage_base(unexpect, std::move(e)) {} + template < + class G = E, + detail::enable_if_t::value> * = nullptr, + detail::enable_if_t::value> * = nullptr> + constexpr expected(unexpected &&e) noexcept( + std::is_nothrow_constructible::value) + : storage_base(unexpect, std::move(e)) {} - template ::value>* = nullptr> - constexpr explicit expected(unexpect_t, Args&&... args) - : storage_base(unexpect, std::forward(args)...) {} + template ::value> * = + nullptr> + constexpr explicit expected(unexpect_t, Args &&... args) + : storage_base(unexpect, std::forward(args)...) {} - template &, Args&&...>::value>* = nullptr> - constexpr explicit expected(unexpect_t, std::initializer_list il, Args&&... args) - : storage_base(unexpect, il, std::forward(args)...) {} + template &, Args &&...>::value> * = nullptr> + constexpr explicit expected(unexpect_t, std::initializer_list il, + Args &&... args) + : storage_base(unexpect, il, std::forward(args)...) {} - constexpr expected(const expected& rhs) { - if (rhs.has_value()) { - ::new (valptr()) T (*rhs); - } - else { - ::new (errptr()) unexpected_type (unexpected(rhs.error())); - } + constexpr expected(const expected &rhs) { + if (rhs.has_value()) { + ::new (valptr()) T(*rhs); + } else { + ::new (errptr()) unexpected_type(unexpected(rhs.error())); } + } - //TODO SFINAE - constexpr expected(expected&& rhs) noexcept(std::is_nothrow_move_constructible::value && std::is_nothrow_move_constructible::value) { - if (rhs.has_value()) { - ::new (valptr()) T (std::move(*rhs)); - } - else { - ::new (errptr()) unexpected_type (unexpected(std::move(rhs.error()))); - } + // TODO SFINAE + constexpr expected(expected &&rhs) noexcept( + std::is_nothrow_move_constructible::value + &&std::is_nothrow_move_constructible::value) { + if (rhs.has_value()) { + ::new (valptr()) T(std::move(*rhs)); + } else { + ::new (errptr()) unexpected_type(unexpected(std::move(rhs.error()))); } + } - //TODO SFINAE - template ::value || !std::is_convertible::value)>* = nullptr> - explicit constexpr expected(const expected& rhs) { - if (rhs.has_value()) { - ::new (valptr()) T (*rhs); - } - else { - ::new (errptr()) unexpected_type (unexpected(rhs.error())); - } + // TODO SFINAE + template ::value || + !std::is_convertible::value)> * = + nullptr> + explicit constexpr expected(const expected &rhs) { + if (rhs.has_value()) { + ::new (valptr()) T(*rhs); + } else { + ::new (errptr()) unexpected_type(unexpected(rhs.error())); } + } - //TODO SFINAE - template ::value || !std::is_convertible::value)>* = nullptr> - explicit constexpr expected(const expected& rhs) { - if (rhs.has_value()) { - ::new (valptr()) T (*rhs); - } - else { - ::new (errptr()) unexpected_type (unexpected(rhs.error())); - } + // TODO SFINAE + template < + class U, class G, + detail::enable_if_t<(!std::is_convertible::value || + !std::is_convertible::value)> * = nullptr> + explicit constexpr expected(const expected &rhs) { + if (rhs.has_value()) { + ::new (valptr()) T(*rhs); + } else { + ::new (errptr()) unexpected_type(unexpected(rhs.error())); } + } - //TODO SFINAE - template ::value || std::is_convertible::value)>* = nullptr> - constexpr expected(expected&& rhs) { - if (rhs.has_value()) { - ::new (valptr()) T (std::move(*rhs)); - } - else { - ::new (errptr()) unexpected_type (unexpected(std::move(rhs.error()))); - } - } - - //TODO SFINAE - template ::value>* = nullptr> - explicit constexpr expected(U&& v) - : expected(in_place, std::forward(v)) - {} - - //TODO SFINAE - template ::value>* = nullptr> - constexpr expected(U&& v) - : expected(in_place, std::forward(v)) - {} - -//TODO - expected& operator=(const expected&); - expected& operator=(expected&&) noexcept; - template expected& operator=(U&&); - template - expected& operator=(const unexpected&); - template - expected& operator=(unexpected&&) noexcept; - template - void emplace(Args&&...); - template - void emplace(std::initializer_list, Args&&...); - -//TODO SFINAE - void swap(expected& rhs) noexcept(std::is_nothrow_move_constructible::value && noexcept(swap(std::declval(), std::declval())) && std::is_nothrow_move_constructible::value && noexcept(swap(std::declval(), std::declval()))) - { - if (has_value() && rhs.has_value()) { - using std::swap; - swap(val(), rhs.val()); - } - else if (!has_value() && rhs.has_value()) { - using std::swap; - swap(err(), rhs.err()); - } - else if (has_value()) { - auto temp = std::move(rhs.err()); - ::new (rhs.valptr()) T (val()); - ::new (errptr()) unexpected_type (std::move(temp)); - std::swap(this->m_has_val, rhs.m_has_val); - } - else { - auto temp = std::move(this->err()); - ::new (valptr()) T (rhs.val()); - ::new (errptr()) unexpected_type (std::move(temp)); - std::swap(this->m_has_val, rhs.m_has_val); - } + // TODO SFINAE + template < + class U, class G, + detail::enable_if_t<(std::is_convertible::value || + std::is_convertible::value)> * = nullptr> + constexpr expected(expected &&rhs) { + if (rhs.has_value()) { + ::new (valptr()) T(std::move(*rhs)); + } else { + ::new (errptr()) unexpected_type(unexpected(std::move(rhs.error()))); } + } - constexpr const T* operator ->() const { return valptr(); } - constexpr T* operator ->() { return valptr(); } - constexpr const T& operator *() const& { return val(); } - constexpr T& operator *() & { return val(); } - constexpr const T&& operator *() const && { return std::move(val()); } - constexpr T&& operator *() && { return std::move(val()); } - constexpr explicit operator bool() const noexcept { return this->m_has_val; } - constexpr bool has_value() const noexcept { return this->m_has_val; } - constexpr const T& value() const& { - if (!has_value()) throw bad_expected_access(err()); - return val(); - } - constexpr T& value() & { - if (!has_value()) throw bad_expected_access(err()); - return val(); - } - constexpr const T&& value() const && { - if (!has_value()) throw bad_expected_access(err()); - return std::move(val()); - } - constexpr T&& value() && { - if (!has_value()) throw bad_expected_access(err()); - return std::move(val()); - } - constexpr const E& error() const& { return err().value(); } - constexpr E& error() & { return err().value(); } - constexpr const E&& error() const && { return std::move(err().value()); } - constexpr E&& error() && { 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 - 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)); + // TODO SFINAE + template ::value> * = nullptr> + explicit constexpr expected(U &&v) : expected(in_place, std::forward(v)) {} + // TODO SFINAE + template ::value> * = nullptr> + constexpr expected(U &&v) : expected(in_place, std::forward(v)) {} + + // TODO + expected &operator=(const expected &); + expected &operator=(expected &&) noexcept; + template expected &operator=(U &&); + template expected &operator=(const unexpected &); + template expected &operator=(unexpected &&) noexcept; + template void emplace(Args &&...); + template + void emplace(std::initializer_list, Args &&...); + + // TODO SFINAE + void swap(expected &rhs) noexcept( + std::is_nothrow_move_constructible::value &&noexcept( + swap(std::declval(), std::declval())) && + std::is_nothrow_move_constructible::value && + noexcept(swap(std::declval(), std::declval()))) { + if (has_value() && rhs.has_value()) { + using std::swap; + swap(val(), rhs.val()); + } else if (!has_value() && rhs.has_value()) { + using std::swap; + swap(err(), rhs.err()); + } else if (has_value()) { + auto temp = std::move(rhs.err()); + ::new (rhs.valptr()) T(val()); + ::new (errptr()) unexpected_type(std::move(temp)); + std::swap(this->m_has_val, rhs.m_has_val); + } else { + auto temp = std::move(this->err()); + ::new (valptr()) T(rhs.val()); + ::new (errptr()) unexpected_type(std::move(temp)); + std::swap(this->m_has_val, rhs.m_has_val); } + } - + constexpr const T *operator->() const { return valptr(); } + constexpr T *operator->() { return valptr(); } + constexpr const T &operator*() const & { return val(); } + constexpr T &operator*() & { return val(); } + constexpr const T &&operator*() const && { return std::move(val()); } + constexpr T &&operator*() && { return std::move(val()); } + constexpr explicit operator bool() const noexcept { return this->m_has_val; } + constexpr bool has_value() const noexcept { return this->m_has_val; } + constexpr const T &value() const & { + if (!has_value()) + throw bad_expected_access(err()); + return val(); + } + constexpr T &value() & { + if (!has_value()) + throw bad_expected_access(err()); + return val(); + } + constexpr const T &&value() const && { + if (!has_value()) + throw bad_expected_access(err()); + return std::move(val()); + } + constexpr T &&value() && { + if (!has_value()) + throw bad_expected_access(err()); + return std::move(val()); + } + constexpr const E &error() const & { return err().value(); } + constexpr E &error() & { return err().value(); } + constexpr const E &&error() const && { return std::move(err().value()); } + constexpr E &&error() && { 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 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)); + } }; +// TODO +template class expected {}; -//TODO -template -class expected { - -}; - - 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); +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& x, const T& v) { - return x.has_value() ? *x == v : false; - } - template - constexpr bool operator==(const T& v, const expected& x) { - return x.has_value() ? *x == v : false; - } - template - constexpr bool operator!=(const expected& x, const T& v) { - return x.has_value() ? *x != v : true; - } - template - constexpr bool operator!=(const T& 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() ? 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 - 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(); - } - - -//TODO is_swappable -template ::value && std::is_move_constructible::value>* = nullptr> -void swap(expected& lhs, expected& rhs) noexcept(noexcept(lhs.swap(rhs))) { - lhs.swap(rhs); +template +constexpr bool operator==(const expected &x, const T &v) { + return x.has_value() ? *x == v : false; } +template +constexpr bool operator==(const T &v, const expected &x) { + return x.has_value() ? *x == v : false; } +template +constexpr bool operator!=(const expected &x, const T &v) { + return x.has_value() ? *x != v : true; +} +template +constexpr bool operator!=(const T &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() ? 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 +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(); +} + +// TODO is_swappable +template ::value && + std::is_move_constructible::value> * = nullptr> +void swap(expected &lhs, + expected &rhs) noexcept(noexcept(lhs.swap(rhs))) { + lhs.swap(rhs); +} +} // namespace tl #endif