diff --git a/expected.hpp b/expected.hpp index 405a2dd..da1f150 100644 --- a/expected.hpp +++ b/expected.hpp @@ -32,19 +32,23 @@ #define TL_EXPECTED_GCC54 #endif -#if (defined(__GNUC__) && __GNUC__ == 4 && __GNUC_MINOR__ <= 9 && !defined(__clang__)) +#if (defined(__GNUC__) && __GNUC__ == 4 && __GNUC_MINOR__ <= 9 && \ + !defined(__clang__)) // GCC < 5 doesn't support overloading on const&& for member functions #define TL_EXPECTED_NO_CONSTRR -//GCC < 5 doesn't support some standard C++11 type traits -#define IS_TRIVIALLY_COPY_CONSTRUCTIBLE(T) std::has_trivial_copy_constructor::value +// GCC < 5 doesn't support some standard C++11 type traits +#define IS_TRIVIALLY_COPY_CONSTRUCTIBLE(T) \ + std::has_trivial_copy_constructor::value #define IS_TRIVIALLY_COPY_ASSIGNABLE(T) std::has_trivial_copy_assign::value // This one will be different for GCC 5.7 if it's ever supported #define IS_TRIVIALLY_DESTRUCTIBLE(T) std::is_trivially_destructible::value #else -#define IS_TRIVIALLY_COPY_CONSTRUCTIBLE(T) std::is_trivially_copy_constructible::value -#define IS_TRIVIALLY_COPY_ASSIGNABLE(T) std::is_trivially_copy_assignable::value +#define IS_TRIVIALLY_COPY_CONSTRUCTIBLE(T) \ + std::is_trivially_copy_constructible::value +#define IS_TRIVIALLY_COPY_ASSIGNABLE(T) \ + std::is_trivially_copy_assignable::value #define IS_TRIVIALLY_DESTRUCTIBLE(T) std::is_trivially_destructible::value #endif @@ -384,9 +388,11 @@ template struct expected_storage_base { }; }; -// 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; +// 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; void hard_reset() noexcept { get().~T(); @@ -399,7 +405,8 @@ template struct expected_storage_base { } template void construct_error(Args &&... args) noexcept { - new (std::addressof(this->m_unexpect)) unexpected(std::forward(args)...); + new (std::addressof(this->m_unexpect)) + unexpected(std::forward(args)...); this->m_has_value = false; } @@ -412,13 +419,13 @@ template struct expected_storage_base { template ::value> * = nullptr> - expected_operations_base &assign(const expected_operations_base &rhs) noexcept { + expected_operations_base & + 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); + } else { + assign_common(rhs); } } @@ -428,14 +435,14 @@ template struct expected_storage_base { detail::enable_if_t::value && std::is_nothrow_move_constructible::value> * = nullptr> - expected_operations_base &assign(const expected_operations_base &rhs) noexcept { + expected_operations_base & + assign(const expected_operations_base &rhs) noexcept { if (!this->m_has_val && rhs.m_has_val) { - T tmp = rhs.get(); + T tmp = rhs.get(); geterr().~unexpected(); - construct(std::move(tmp)); - } - else { - assign_common(rhs); + construct(std::move(tmp)); + } else { + assign_common(rhs); } } @@ -454,14 +461,13 @@ template struct expected_storage_base { geterr().~unexpected(); try { - construct(rhs.get()); + construct(rhs.get()); } catch (...) { - geterr() = std::move(tmp); + geterr() = std::move(tmp); throw; } - } - else { - assign_common(rhs); + } else { + assign_common(rhs); } } @@ -471,12 +477,10 @@ template struct expected_storage_base { * = nullptr> expected_operations_base &assign(expected_operations_base &&rhs) noexcept { if (!this->m_has_val && rhs.m_has_val) { - geterr().~unexpected(); - ::new (valptr()) T(*std::move(rhs)); - this->m_has_val = true; - } - else { - assign_common(rhs); + geterr().~unexpected(); + construct(std::move(rhs).get()); + } else { + assign_common(rhs); } } @@ -488,14 +492,13 @@ template struct expected_storage_base { auto tmp = std::move(geterr()); geterr().~unexpected(); try { - construct(std::move(rhs).get()); + construct(std::move(rhs).get()); } catch (...) { - geterr() = std::move(tmp); + geterr() = std::move(tmp); throw; } - } - else { - assign_common(rhs); + } else { + assign_common(rhs); } } @@ -503,19 +506,19 @@ template struct expected_storage_base { template void assign_common(Rhs &&rhs) { if (this->m_has_val) { if (rhs.m_has_val) { - get() = std::forward(rhs).get(); + get() = std::forward(rhs).get(); } else { get().~T(); construct_err(std::forward(rhs).geterr()); } } else { if (!rhs.m_has_val) { - geterr() = std::forward(rhs).geterr(); + geterr() = std::forward(rhs).geterr(); } } } - bool has_value() const { return this->m_has_value; } + bool has_value() const { return this->m_has_value; } TL_EXPECTED_11_CONSTEXPR T &get() & { return this->m_val; } TL_EXPECTED_11_CONSTEXPR const T &get() const & { return this->m_val; } @@ -525,7 +528,9 @@ template struct expected_storage_base { #endif TL_EXPECTED_11_CONSTEXPR T &geterr() & { return this->m_unexpect; } - TL_EXPECTED_11_CONSTEXPR const T &geterr() const & { return this->m_unexpect; } + TL_EXPECTED_11_CONSTEXPR const T &geterr() const & { + return this->m_unexpect; + } TL_EXPECTED_11_CONSTEXPR T &&geterr() && { std::move(this->m_unexpect); } #ifndef TL_EXPECTED_NO_CONSTRR constexpr const T &&geterr() const && { return std::move(this->m_unexpect); } @@ -534,22 +539,22 @@ template struct expected_storage_base { // This class manages conditionally having a trivial copy constructor // This specialization is for when T is trivially copy constructible - template - struct expected_copy_base : expected_operations_base { - using expected_operations_base::expected_operations_base; +template +struct expected_copy_base : expected_operations_base { + using expected_operations_base::expected_operations_base; }; // This specialization is for when T is not trivially copy constructible - template - struct expected_copy_base : expected_operations_base { - using expected_operations_base::expected_operations_base; +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) { if (rhs.has_value()) { this->construct(rhs.get()); } else { - this->construct_error(rhs.geterr()); + this->construct_error(rhs.geterr()); } } @@ -559,18 +564,22 @@ template struct expected_storage_base { }; // 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 +// 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> - struct expected_move_base : expected_copy_base { - using expected_copy_base::expected_copy_base; +template ::value> +struct expected_move_base : expected_copy_base { + using expected_copy_base::expected_copy_base; }; #else - template - struct expected_move_base; - #endif - template struct expected_move_base : expected_copy_base { - using expected_copy_base::expected_copy_base; +template struct expected_move_base; +#endif +template +struct expected_move_base : expected_copy_base { + using expected_copy_base::expected_copy_base; expected_move_base() = default; expected_move_base(const expected_move_base &rhs) = default; @@ -588,42 +597,50 @@ template struct expected_storage_base { }; // This class manages conditionally having a trivial copy assignment operator - template - 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; }; - template - 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); + this->assign(rhs); } 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 +// 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 ::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; +template ::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; }; #else - template - struct expected_move_assign_base; +template struct expected_move_assign_base; #endif - template - struct expected_move_assign_base : expected_copy_assign_base { - using expected_copy_assign_base::expected_copy_assign_base; +template +struct expected_move_assign_base + : expected_copy_assign_base { + using expected_copy_assign_base::expected_copy_assign_base; expected_move_assign_base() = default; expected_move_assign_base(const expected_move_assign_base &rhs) = default; @@ -633,15 +650,19 @@ template struct expected_storage_base { operator=(const expected_move_assign_base &rhs) noexcept( std::is_nothrow_move_constructible::value &&std::is_nothrow_move_assignable::value) { - this->assign(std::move(rhs)); + this->assign(std::move(rhs)); } expected_move_assign_base & operator=(expected_move_assign_base &&rhs) = default; }; -// 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 = (std::is_move_constructible::value && std::is_move_constructible::value)> +// 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 = (std::is_move_constructible::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; @@ -652,7 +673,8 @@ struct expected_delete_ctor_base { operator=(expected_delete_ctor_base &&) noexcept = default; }; -template struct expected_delete_ctor_base { +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; @@ -662,7 +684,8 @@ template struct expected_delete_ctor_base { operator=(expected_delete_ctor_base &&) noexcept = default; }; -template struct expected_delete_ctor_base { +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; @@ -672,7 +695,8 @@ template struct expected_delete_ctor_base { operator=(expected_delete_ctor_base &&) noexcept = default; }; -template struct expected_delete_ctor_base { +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; @@ -682,8 +706,10 @@ template struct expected_delete_ctor_base { operator=(expected_delete_ctor_base &&) noexcept = default; }; -// expected_delete_assign_base will conditionally delete copy and move constructors depending on whether T is copy/move constructible + assignable -template ::value && std::is_copy_constructible::value && std::is_copy_assignable::value && @@ -703,7 +729,8 @@ struct expected_delete_assign_base { operator=(expected_delete_assign_base &&) noexcept = default; }; -template struct expected_delete_assign_base { +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 = @@ -714,7 +741,8 @@ template struct expected_delete_assign_base { operator=(expected_delete_assign_base &&) noexcept = delete; }; -template struct expected_delete_assign_base { +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 = @@ -725,7 +753,8 @@ template struct expected_delete_assign_base { operator=(expected_delete_assign_base &&) noexcept = default; }; -template struct expected_delete_assign_base { +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 = @@ -802,7 +831,7 @@ private: /// has been destroyed. The initialization state of the contained object is /// tracked by the expected object. template -class expected : private detail::expected_move_assign, +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 { @@ -823,7 +852,7 @@ class expected : private detail::expected_move_assign, const T &val() const { return this->m_val; } const unexpected &err() const { return this->m_unexpect; } - using impl_base = detail::expected_impl; + using impl_base = detail::expected_move_assign_base; using ctor_base = detail::expected_default_ctor_base; public: