113 changes: 70 additions & 43 deletions single-header/outcome-basic.hpp
Expand Up @@ -80,7 +80,7 @@ Distributed under the Boost Software License, Version 1.0.
#define OUTCOME_VERSION_REVISION 0 // Revision version for cmake and DLL version stamping
/*! AWAITING HUGO JSON CONVERSION TOOL */
// Pull in detection of __MINGW64_VERSION_MAJOR
#if defined(__MINGW32__) && !0L
#if defined(__MINGW32__) && !0
#include <_mingw.h>
#endif
/* Configure QuickCppLib
Expand Down Expand Up @@ -132,7 +132,7 @@ Distributed under the Boost Software License, Version 1.0.
*/
#ifndef QUICKCPPLIB_HAS_FEATURE_H
#define QUICKCPPLIB_HAS_FEATURE_H
#if __cplusplus >= 201103L
#if __cplusplus >= 201103
// Some of these macros ended up getting removed by ISO standards,
// they are prefixed with ////
////#if !defined(__cpp_alignas)
Expand Down Expand Up @@ -193,7 +193,7 @@ Distributed under the Boost Software License, Version 1.0.
#define __cpp_attributes 190000
#endif
#if !defined(__cpp_constexpr)
#if __cplusplus >= 201402L
#if __cplusplus >= 201402
#define __cpp_constexpr 201304 // relaxed constexpr
#else
#define __cpp_constexpr 190000
Expand Down Expand Up @@ -248,7 +248,7 @@ Distributed under the Boost Software License, Version 1.0.
#define __cpp_variadic_templates 190000
#endif
#endif
#if __cplusplus >= 201402L
#if __cplusplus >= 201402
// Some of these macros ended up getting removed by ISO standards,
// they are prefixed with ////
////#if !defined(__cpp_contextual_conversions)
Expand Down Expand Up @@ -671,7 +671,7 @@ extern "C" void _mm_pause();
#endif
#endif
#ifndef QUICKCPPLIB_NODISCARD
#if 0L || (_HAS_CXX17 && _MSC_VER >= 1911 /* VS2017.3 */)
#if 0 || (_HAS_CXX17 && _MSC_VER >= 1911 /* VS2017.3 */)
#define QUICKCPPLIB_NODISCARD [[nodiscard]]
#endif
#endif
Expand Down Expand Up @@ -718,7 +718,7 @@ extern "C" void _mm_pause();
#ifndef QUICKCPPLIB_THREAD_LOCAL
#if _MSC_VER >= 1800
#define QUICKCPPLIB_THREAD_LOCAL_IS_CXX11 1
#elif __cplusplus >= 201103L
#elif __cplusplus >= 201103
#if __GNUC__ >= 5 && !defined(__clang__)
#define QUICKCPPLIB_THREAD_LOCAL_IS_CXX11 1
#elif defined(__has_feature)
Expand Down Expand Up @@ -979,9 +979,9 @@ Distributed under the Boost Software License, Version 1.0.
http://www.boost.org/LICENSE_1_0.txt)
*/
// Note the second line of this file must ALWAYS be the git SHA, third line ALWAYS the git SHA update time
#define OUTCOME_PREVIOUS_COMMIT_REF 147ec1e8673c34cb7cf431dfdbf211d8072d7656
#define OUTCOME_PREVIOUS_COMMIT_DATE "2022-03-17 19:38:05 +00:00"
#define OUTCOME_PREVIOUS_COMMIT_UNIQUE 147ec1e8
#define OUTCOME_PREVIOUS_COMMIT_REF 5e36246352c1c412813583e446eea0d1a19d08cc
#define OUTCOME_PREVIOUS_COMMIT_DATE "2022-04-05 06:23:15 +00:00"
#define OUTCOME_PREVIOUS_COMMIT_UNIQUE 5e362463
#define OUTCOME_V2 (QUICKCPPLIB_BIND_NAMESPACE_VERSION(outcome_v2))
#ifdef _DEBUG
#define OUTCOME_V2_CXX_MODULE_NAME QUICKCPPLIB_BIND_NAMESPACE((QUICKCPPLIB_BIND_NAMESPACE_VERSION(outcome_v2d)))
Expand Down Expand Up @@ -1043,7 +1043,7 @@ template <class T> constexpr in_place_type_t<T> in_place_type{};
OUTCOME_V2_NAMESPACE_END
#endif
#ifndef OUTCOME_TRIVIAL_ABI
#if 0L || __clang_major__ >= 7
#if 0 || __clang_major__ >= 7
//! Defined to be `[[clang::trivial_abi]]` when on a new enough clang compiler. Usually automatic, can be overriden.
#define OUTCOME_TRIVIAL_ABI [[clang::trivial_abi]]
#else
Expand Down Expand Up @@ -1168,7 +1168,7 @@ namespace detail
#endif
#endif
// True if type is nothrow swappable
#if !0L && OUTCOME_USE_STD_IS_NOTHROW_SWAPPABLE
#if !0 && OUTCOME_USE_STD_IS_NOTHROW_SWAPPABLE
template <class T> using is_nothrow_swappable = std::is_nothrow_swappable<T>;
#else
template <class T> struct is_nothrow_swappable
Expand Down Expand Up @@ -1220,7 +1220,7 @@ Distributed under the Boost Software License, Version 1.0.
#ifdef QUICKCPPLIB_EXPORTS
#define EXECINFO_DECL extern __declspec(dllexport)
#else
#if defined(__cplusplus) && (!defined(QUICKCPPLIB_HEADERS_ONLY) || QUICKCPPLIB_HEADERS_ONLY == 1) && !0L
#if defined(__cplusplus) && (!defined(QUICKCPPLIB_HEADERS_ONLY) || QUICKCPPLIB_HEADERS_ONLY == 1) && !0
#define EXECINFO_DECL inline
#elif defined(QUICKCPPLIB_DYN_LINK) && !defined(QUICKCPPLIB_STATIC_LINK)
#define EXECINFO_DECL extern __declspec(dllimport)
Expand All @@ -1238,7 +1238,7 @@ EXECINFO_DECL _Check_return_ _Ret_writes_maybenull_(len) char **backtrace_symbol
// extern void backtrace_symbols_fd(void *const *bt, size_t len, int fd);
#ifdef __cplusplus
}
#if (!defined(QUICKCPPLIB_HEADERS_ONLY) || QUICKCPPLIB_HEADERS_ONLY == 1) && !0L
#if (!defined(QUICKCPPLIB_HEADERS_ONLY) || QUICKCPPLIB_HEADERS_ONLY == 1) && !0
#define QUICKCPPLIB_INCLUDED_BY_HEADER 1
/* Implements backtrace() et al from glibc on win64
(C) 2016-2017 Niall Douglas <http://www.nedproductions.biz/> (14 commits)
Expand Down Expand Up @@ -2020,19 +2020,32 @@ namespace detail
// Prefer to use move or copy construction
template <class T> struct move_assign_to_empty<T, true, false>
{
move_assign_to_empty(T *dest, T &&o) noexcept(std::is_nothrow_move_constructible<T>::value) { new(dest) T(static_cast<T &&>(o)); }
move_assign_to_empty(T *dest, T *o) noexcept(std::is_nothrow_move_constructible<T>::value) { new(dest) T(static_cast<T &&>(*o)); }
};
template <class T> struct move_assign_to_empty<T, true, true>
{
move_assign_to_empty(T *dest, T &&o) noexcept(std::is_nothrow_move_constructible<T>::value) { new(dest) T(static_cast<T &&>(o)); }
move_assign_to_empty(T *dest, T *o) noexcept(std::is_nothrow_move_constructible<T>::value) { new(dest) T(static_cast<T &&>(*o)); }
};
// But fall back on default construction and move assign if necessary
template <class T> struct move_assign_to_empty<T, false, true>
{
move_assign_to_empty(T *dest, T &&o) noexcept(std::is_nothrow_default_constructible<T>::value &&std::is_nothrow_move_assignable<T>::value)
move_assign_to_empty(T *dest, T *o) noexcept(std::is_nothrow_default_constructible<T>::value &&std::is_nothrow_move_assignable<T>::value)
{
new(dest) T;
*dest = static_cast<T &&>(o);
*dest = static_cast<T &&>(*o);
}
};
// Void does nothing
template <> struct move_assign_to_empty<void, false, false>
{
move_assign_to_empty(void *, void *) noexcept
{ /* nothing to assign */
}
};
template <> struct move_assign_to_empty<const void, false, false>
{
move_assign_to_empty(const void *, const void *) noexcept
{ /* nothing to assign */
}
};
// Helpers for copy assigning to empty storage
Expand All @@ -2042,19 +2055,32 @@ namespace detail
// Prefer to use copy construction
template <class T> struct copy_assign_to_empty<T, true, false>
{
copy_assign_to_empty(T *dest, const T &o) noexcept(std::is_nothrow_copy_constructible<T>::value) { new(dest) T(o); }
copy_assign_to_empty(T *dest, const T *o) noexcept(std::is_nothrow_copy_constructible<T>::value) { new(dest) T(*o); }
};
template <class T> struct copy_assign_to_empty<T, true, true>
{
copy_assign_to_empty(T *dest, const T &o) noexcept(std::is_nothrow_copy_constructible<T>::value) { new(dest) T(o); }
copy_assign_to_empty(T *dest, const T *o) noexcept(std::is_nothrow_copy_constructible<T>::value) { new(dest) T(*o); }
};
// But fall back on default construction and copy assign if necessary
template <class T> struct copy_assign_to_empty<T, false, true>
{
copy_assign_to_empty(T *dest, const T &o) noexcept(std::is_nothrow_default_constructible<T>::value &&std::is_nothrow_copy_assignable<T>::value)
copy_assign_to_empty(T *dest, const T *o) noexcept(std::is_nothrow_default_constructible<T>::value &&std::is_nothrow_copy_assignable<T>::value)
{
new(dest) T;
*dest = o;
*dest = *o;
}
};
// Void does nothing
template <> struct copy_assign_to_empty<void, false, false>
{
copy_assign_to_empty(void *, void *) noexcept
{ /* nothing to assign */
}
};
template <> struct copy_assign_to_empty<const void, false, false>
{
copy_assign_to_empty(const void *, const void *) noexcept
{ /* nothing to assign */
}
};
template <class T, bool nothrow> struct strong_swap_impl
Expand Down Expand Up @@ -2511,7 +2537,7 @@ namespace detail
empty_type _empty2;
_error_type_ _error;
};
#if __cplusplus >= 202000L || _HAS_CXX20
#if __cplusplus >= 202000 || _HAS_CXX20
constexpr
#endif
value_storage_nontrivial() noexcept
Expand All @@ -2521,7 +2547,7 @@ namespace detail
}
value_storage_nontrivial &operator=(const value_storage_nontrivial &) = default; // if reaches here, copy assignment is trivial
value_storage_nontrivial &operator=(value_storage_nontrivial &&) = default; // NOLINT if reaches here, move assignment is trivial
#if __cplusplus >= 202000L || _HAS_CXX20
#if __cplusplus >= 202000 || _HAS_CXX20
constexpr
#endif
value_storage_nontrivial(value_storage_nontrivial &&o) noexcept(
Expand All @@ -2538,7 +2564,7 @@ namespace detail
_status = o._status;
o._status.set_have_moved_from(true);
}
#if __cplusplus >= 202000L || _HAS_CXX20
#if __cplusplus >= 202000 || _HAS_CXX20
constexpr
#endif
value_storage_nontrivial(const value_storage_nontrivial &o) noexcept(
Expand All @@ -2554,7 +2580,7 @@ namespace detail
}
_status = o._status;
}
#if __cplusplus >= 202000L || _HAS_CXX20
#if __cplusplus >= 202000 || _HAS_CXX20
constexpr
#endif
explicit value_storage_nontrivial(status_bitfield_type status)
Expand Down Expand Up @@ -2714,7 +2740,7 @@ namespace detail
_status = o._status;
o._status.set_have_moved_from(true);
}
#if __cplusplus >= 202000L || _HAS_CXX20
#if __cplusplus >= 202000 || _HAS_CXX20
constexpr
#endif
~value_storage_nontrivial() noexcept(std::is_nothrow_destructible<_value_type_>::value &&std::is_nothrow_destructible<_error_type_>::value)
Expand All @@ -2736,7 +2762,7 @@ namespace detail
this->_status.set_have_error(false);
}
}
#if __cplusplus >= 202000L || _HAS_CXX20
#if __cplusplus >= 202000 || _HAS_CXX20
constexpr
#endif
void
Expand Down Expand Up @@ -2933,14 +2959,15 @@ namespace detail
value_storage_nontrivial_move_assignment(value_storage_nontrivial_move_assignment &&) = default; // NOLINT
value_storage_nontrivial_move_assignment &operator=(const value_storage_nontrivial_move_assignment &o) = default;
~value_storage_nontrivial_move_assignment() = default;
#if __cplusplus >= 202000L || _HAS_CXX20
#if __cplusplus >= 202000 || _HAS_CXX20
constexpr
#endif
value_storage_nontrivial_move_assignment &
operator=(value_storage_nontrivial_move_assignment &&o) noexcept(
std::is_nothrow_move_assignable<value_type>::value &&std::is_nothrow_move_assignable<error_type>::value &&noexcept(move_assign_to_empty<value_type>(
static_cast<value_type *>(nullptr), std::declval<value_type>())) &&noexcept(move_assign_to_empty<error_type>(static_cast<error_type *>(nullptr),
std::declval<error_type>()))) // NOLINT
static_cast<value_type *>(nullptr),
static_cast<value_type *>(nullptr))) &&noexcept(move_assign_to_empty<error_type>(static_cast<error_type *>(nullptr),
static_cast<error_type *>(nullptr)))) // NOLINT
{
using _value_type_ = typename Base::_value_type_;
using _error_type_ = typename Base::_error_type_;
Expand Down Expand Up @@ -2976,7 +3003,7 @@ namespace detail
}
if(!this->_status.have_value() && !this->_status.have_error() && o._status.have_value())
{
move_assign_to_empty<_value_type_>(&this->_value, static_cast<_value_type_ &&>(o._value));
move_assign_to_empty<_value_type_>(&this->_value, &o._value);
this->_status = o._status;
o._status.set_have_moved_from(true);
return *this;
Expand All @@ -2993,7 +3020,7 @@ namespace detail
}
if(!this->_status.have_value() && !this->_status.have_error() && o._status.have_error())
{
move_assign_to_empty<_error_type_>(&this->_error, static_cast<_error_type_ &&>(o._error));
move_assign_to_empty<_error_type_>(&this->_error, &o._error);
this->_status = o._status;
o._status.set_have_moved_from(true);
return *this;
Expand All @@ -3004,7 +3031,7 @@ namespace detail
{
this->_value.~_value_type_(); // NOLINT
}
move_assign_to_empty<_error_type_>(&this->_error, static_cast<_error_type_ &&>(o._error));
move_assign_to_empty<_error_type_>(&this->_error, &o._error);
this->_status = o._status;
o._status.set_have_moved_from(true);
return *this;
Expand All @@ -3015,7 +3042,7 @@ namespace detail
{
this->_error.~_error_type_(); // NOLINT
}
move_assign_to_empty<_value_type_>(&this->_value, static_cast<_value_type_ &&>(o._value));
move_assign_to_empty<_value_type_>(&this->_value, &o._value);
this->_status = o._status;
o._status.set_have_moved_from(true);
return *this;
Expand All @@ -3034,14 +3061,14 @@ namespace detail
value_storage_nontrivial_copy_assignment(value_storage_nontrivial_copy_assignment &&) = default; // NOLINT
value_storage_nontrivial_copy_assignment &operator=(value_storage_nontrivial_copy_assignment &&o) = default; // NOLINT
~value_storage_nontrivial_copy_assignment() = default;
#if __cplusplus >= 202000L || _HAS_CXX20
#if __cplusplus >= 202000 || _HAS_CXX20
constexpr
#endif
value_storage_nontrivial_copy_assignment &
operator=(const value_storage_nontrivial_copy_assignment &o) noexcept(
std::is_nothrow_copy_assignable<value_type>::value &&std::is_nothrow_copy_assignable<error_type>::value &&noexcept(copy_assign_to_empty<value_type>(
static_cast<value_type *>(nullptr), std::declval<value_type>())) &&noexcept(copy_assign_to_empty<error_type>(static_cast<error_type *>(nullptr),
std::declval<error_type>())))
static_cast<value_type *>(nullptr), static_cast<value_type *>(nullptr))) &&noexcept(copy_assign_to_empty<error_type>(static_cast<error_type *>(nullptr),
static_cast<error_type *>(nullptr))))
{
using _value_type_ = typename Base::_value_type_;
using _error_type_ = typename Base::_error_type_;
Expand Down Expand Up @@ -3073,7 +3100,7 @@ namespace detail
}
if(!this->_status.have_value() && !this->_status.have_error() && o._status.have_value())
{
copy_assign_to_empty<_value_type_>(&this->_value, o._value);
copy_assign_to_empty<_value_type_>(&this->_value, &o._value);
this->_status = o._status;
return *this;
}
Expand All @@ -3088,7 +3115,7 @@ namespace detail
}
if(!this->_status.have_value() && !this->_status.have_error() && o._status.have_error())
{
copy_assign_to_empty<_error_type_>(&this->_error, o._error);
copy_assign_to_empty<_error_type_>(&this->_error, &o._error);
this->_status = o._status;
return *this;
}
Expand All @@ -3098,7 +3125,7 @@ namespace detail
{
this->_value.~_value_type_(); // NOLINT
}
copy_assign_to_empty<_error_type_>(&this->_error, o._error);
copy_assign_to_empty<_error_type_>(&this->_error, &o._error);
this->_status = o._status;
return *this;
}
Expand All @@ -3108,7 +3135,7 @@ namespace detail
{
this->_error.~_error_type_(); // NOLINT
}
copy_assign_to_empty<_value_type_>(&this->_value, o._value);
copy_assign_to_empty<_value_type_>(&this->_value, &o._value);
this->_status = o._status;
return *this;
}
Expand Down Expand Up @@ -5842,7 +5869,7 @@ SIGNATURE NOT RECOGNISED
};
// C++ 20 operator== rewriting should take care of this for us, indeed
// if we don't disable it, we cause Concept recursion to infinity!
#if __cplusplus < 202000L && !_HAS_CXX20
#if __cplusplus < 202000 && !_HAS_CXX20
/*! AWAITING HUGO JSON CONVERSION TOOL
SIGNATURE NOT RECOGNISED
*/
Expand Down Expand Up @@ -6147,7 +6174,7 @@ OUTCOME_V2_NAMESPACE_END
#define _OUTCOME_TRY_OVERLOAD_GLUE(x, y) x y
#define _OUTCOME_TRY_CALL_OVERLOAD(name, ...) _OUTCOME_TRY_OVERLOAD_GLUE(_OUTCOME_TRY_OVERLOAD_MACRO(name, _OUTCOME_TRY_COUNT_ARGS_MAX8(__VA_ARGS__)), (__VA_ARGS__))
#ifndef OUTCOME_TRY_LIKELY_IF
#if (__cplusplus >= 202000L || _HAS_CXX20) && (!defined(__clang__) || __clang_major__ >= 12) && (!defined(__GNUC__) || defined(__clang__) || __GNUC__ >= 9)
#if (__cplusplus >= 202000 || _HAS_CXX20) && (!defined(__clang__) || __clang_major__ >= 12) && (!defined(__GNUC__) || defined(__clang__) || __GNUC__ >= 9)
#define OUTCOME_TRY_LIKELY_IF(...) if(__VA_ARGS__) [[likely]]
#elif defined(__clang__) || defined(__GNUC__)
#define OUTCOME_TRY_LIKELY_IF(...) if(__builtin_expect(!!(__VA_ARGS__), true))
Expand Down
159 changes: 93 additions & 66 deletions single-header/outcome-experimental.hpp

Large diffs are not rendered by default.

115 changes: 71 additions & 44 deletions single-header/outcome.hpp
Expand Up @@ -21,7 +21,7 @@ Distributed under the Boost Software License, Version 1.0.
(See accompanying file Licence.txt or copy at
http://www.boost.org/LICENSE_1_0.txt)
*/
#if !OUTCOME_ENABLE_CXX_MODULES || !0L || defined(GENERATING_OUTCOME_MODULE_INTERFACE) || OUTCOME_DISABLE_CXX_MODULES
#if !OUTCOME_ENABLE_CXX_MODULES || !0 || defined(GENERATING_OUTCOME_MODULE_INTERFACE) || OUTCOME_DISABLE_CXX_MODULES
/* Tells C++ coroutines about Outcome's result
(C) 2019 Niall Douglas <http://www.nedproductions.biz/> (12 commits)
File Created: Oct 2019
Expand Down Expand Up @@ -104,7 +104,7 @@ Distributed under the Boost Software License, Version 1.0.
#define OUTCOME_VERSION_REVISION 0 // Revision version for cmake and DLL version stamping
/*! AWAITING HUGO JSON CONVERSION TOOL */
// Pull in detection of __MINGW64_VERSION_MAJOR
#if defined(__MINGW32__) && !0L
#if defined(__MINGW32__) && !0
#include <_mingw.h>
#endif
/* Configure QuickCppLib
Expand Down Expand Up @@ -156,7 +156,7 @@ Distributed under the Boost Software License, Version 1.0.
*/
#ifndef QUICKCPPLIB_HAS_FEATURE_H
#define QUICKCPPLIB_HAS_FEATURE_H
#if __cplusplus >= 201103L
#if __cplusplus >= 201103
// Some of these macros ended up getting removed by ISO standards,
// they are prefixed with ////
////#if !defined(__cpp_alignas)
Expand Down Expand Up @@ -217,7 +217,7 @@ Distributed under the Boost Software License, Version 1.0.
#define __cpp_attributes 190000
#endif
#if !defined(__cpp_constexpr)
#if __cplusplus >= 201402L
#if __cplusplus >= 201402
#define __cpp_constexpr 201304 // relaxed constexpr
#else
#define __cpp_constexpr 190000
Expand Down Expand Up @@ -272,7 +272,7 @@ Distributed under the Boost Software License, Version 1.0.
#define __cpp_variadic_templates 190000
#endif
#endif
#if __cplusplus >= 201402L
#if __cplusplus >= 201402
// Some of these macros ended up getting removed by ISO standards,
// they are prefixed with ////
////#if !defined(__cpp_contextual_conversions)
Expand Down Expand Up @@ -695,7 +695,7 @@ extern "C" void _mm_pause();
#endif
#endif
#ifndef QUICKCPPLIB_NODISCARD
#if 0L || (_HAS_CXX17 && _MSC_VER >= 1911 /* VS2017.3 */)
#if 0 || (_HAS_CXX17 && _MSC_VER >= 1911 /* VS2017.3 */)
#define QUICKCPPLIB_NODISCARD [[nodiscard]]
#endif
#endif
Expand Down Expand Up @@ -742,7 +742,7 @@ extern "C" void _mm_pause();
#ifndef QUICKCPPLIB_THREAD_LOCAL
#if _MSC_VER >= 1800
#define QUICKCPPLIB_THREAD_LOCAL_IS_CXX11 1
#elif __cplusplus >= 201103L
#elif __cplusplus >= 201103
#if __GNUC__ >= 5 && !defined(__clang__)
#define QUICKCPPLIB_THREAD_LOCAL_IS_CXX11 1
#elif defined(__has_feature)
Expand Down Expand Up @@ -1003,9 +1003,9 @@ Distributed under the Boost Software License, Version 1.0.
http://www.boost.org/LICENSE_1_0.txt)
*/
// Note the second line of this file must ALWAYS be the git SHA, third line ALWAYS the git SHA update time
#define OUTCOME_PREVIOUS_COMMIT_REF 147ec1e8673c34cb7cf431dfdbf211d8072d7656
#define OUTCOME_PREVIOUS_COMMIT_DATE "2022-03-17 19:38:05 +00:00"
#define OUTCOME_PREVIOUS_COMMIT_UNIQUE 147ec1e8
#define OUTCOME_PREVIOUS_COMMIT_REF 5e36246352c1c412813583e446eea0d1a19d08cc
#define OUTCOME_PREVIOUS_COMMIT_DATE "2022-04-05 06:23:15 +00:00"
#define OUTCOME_PREVIOUS_COMMIT_UNIQUE 5e362463
#define OUTCOME_V2 (QUICKCPPLIB_BIND_NAMESPACE_VERSION(outcome_v2))
#ifdef _DEBUG
#define OUTCOME_V2_CXX_MODULE_NAME QUICKCPPLIB_BIND_NAMESPACE((QUICKCPPLIB_BIND_NAMESPACE_VERSION(outcome_v2d)))
Expand Down Expand Up @@ -1067,7 +1067,7 @@ template <class T> constexpr in_place_type_t<T> in_place_type{};
OUTCOME_V2_NAMESPACE_END
#endif
#ifndef OUTCOME_TRIVIAL_ABI
#if 0L || __clang_major__ >= 7
#if 0 || __clang_major__ >= 7
//! Defined to be `[[clang::trivial_abi]]` when on a new enough clang compiler. Usually automatic, can be overriden.
#define OUTCOME_TRIVIAL_ABI [[clang::trivial_abi]]
#else
Expand Down Expand Up @@ -1192,7 +1192,7 @@ namespace detail
#endif
#endif
// True if type is nothrow swappable
#if !0L && OUTCOME_USE_STD_IS_NOTHROW_SWAPPABLE
#if !0 && OUTCOME_USE_STD_IS_NOTHROW_SWAPPABLE
template <class T> using is_nothrow_swappable = std::is_nothrow_swappable<T>;
#else
template <class T> struct is_nothrow_swappable
Expand Down Expand Up @@ -1244,7 +1244,7 @@ Distributed under the Boost Software License, Version 1.0.
#ifdef QUICKCPPLIB_EXPORTS
#define EXECINFO_DECL extern __declspec(dllexport)
#else
#if defined(__cplusplus) && (!defined(QUICKCPPLIB_HEADERS_ONLY) || QUICKCPPLIB_HEADERS_ONLY == 1) && !0L
#if defined(__cplusplus) && (!defined(QUICKCPPLIB_HEADERS_ONLY) || QUICKCPPLIB_HEADERS_ONLY == 1) && !0
#define EXECINFO_DECL inline
#elif defined(QUICKCPPLIB_DYN_LINK) && !defined(QUICKCPPLIB_STATIC_LINK)
#define EXECINFO_DECL extern __declspec(dllimport)
Expand All @@ -1262,7 +1262,7 @@ EXECINFO_DECL _Check_return_ _Ret_writes_maybenull_(len) char **backtrace_symbol
// extern void backtrace_symbols_fd(void *const *bt, size_t len, int fd);
#ifdef __cplusplus
}
#if (!defined(QUICKCPPLIB_HEADERS_ONLY) || QUICKCPPLIB_HEADERS_ONLY == 1) && !0L
#if (!defined(QUICKCPPLIB_HEADERS_ONLY) || QUICKCPPLIB_HEADERS_ONLY == 1) && !0
#define QUICKCPPLIB_INCLUDED_BY_HEADER 1
/* Implements backtrace() et al from glibc on win64
(C) 2016-2017 Niall Douglas <http://www.nedproductions.biz/> (14 commits)
Expand Down Expand Up @@ -2655,19 +2655,32 @@ namespace detail
// Prefer to use move or copy construction
template <class T> struct move_assign_to_empty<T, true, false>
{
move_assign_to_empty(T *dest, T &&o) noexcept(std::is_nothrow_move_constructible<T>::value) { new(dest) T(static_cast<T &&>(o)); }
move_assign_to_empty(T *dest, T *o) noexcept(std::is_nothrow_move_constructible<T>::value) { new(dest) T(static_cast<T &&>(*o)); }
};
template <class T> struct move_assign_to_empty<T, true, true>
{
move_assign_to_empty(T *dest, T &&o) noexcept(std::is_nothrow_move_constructible<T>::value) { new(dest) T(static_cast<T &&>(o)); }
move_assign_to_empty(T *dest, T *o) noexcept(std::is_nothrow_move_constructible<T>::value) { new(dest) T(static_cast<T &&>(*o)); }
};
// But fall back on default construction and move assign if necessary
template <class T> struct move_assign_to_empty<T, false, true>
{
move_assign_to_empty(T *dest, T &&o) noexcept(std::is_nothrow_default_constructible<T>::value &&std::is_nothrow_move_assignable<T>::value)
move_assign_to_empty(T *dest, T *o) noexcept(std::is_nothrow_default_constructible<T>::value &&std::is_nothrow_move_assignable<T>::value)
{
new(dest) T;
*dest = static_cast<T &&>(o);
*dest = static_cast<T &&>(*o);
}
};
// Void does nothing
template <> struct move_assign_to_empty<void, false, false>
{
move_assign_to_empty(void *, void *) noexcept
{ /* nothing to assign */
}
};
template <> struct move_assign_to_empty<const void, false, false>
{
move_assign_to_empty(const void *, const void *) noexcept
{ /* nothing to assign */
}
};
// Helpers for copy assigning to empty storage
Expand All @@ -2677,19 +2690,32 @@ namespace detail
// Prefer to use copy construction
template <class T> struct copy_assign_to_empty<T, true, false>
{
copy_assign_to_empty(T *dest, const T &o) noexcept(std::is_nothrow_copy_constructible<T>::value) { new(dest) T(o); }
copy_assign_to_empty(T *dest, const T *o) noexcept(std::is_nothrow_copy_constructible<T>::value) { new(dest) T(*o); }
};
template <class T> struct copy_assign_to_empty<T, true, true>
{
copy_assign_to_empty(T *dest, const T &o) noexcept(std::is_nothrow_copy_constructible<T>::value) { new(dest) T(o); }
copy_assign_to_empty(T *dest, const T *o) noexcept(std::is_nothrow_copy_constructible<T>::value) { new(dest) T(*o); }
};
// But fall back on default construction and copy assign if necessary
template <class T> struct copy_assign_to_empty<T, false, true>
{
copy_assign_to_empty(T *dest, const T &o) noexcept(std::is_nothrow_default_constructible<T>::value &&std::is_nothrow_copy_assignable<T>::value)
copy_assign_to_empty(T *dest, const T *o) noexcept(std::is_nothrow_default_constructible<T>::value &&std::is_nothrow_copy_assignable<T>::value)
{
new(dest) T;
*dest = o;
*dest = *o;
}
};
// Void does nothing
template <> struct copy_assign_to_empty<void, false, false>
{
copy_assign_to_empty(void *, void *) noexcept
{ /* nothing to assign */
}
};
template <> struct copy_assign_to_empty<const void, false, false>
{
copy_assign_to_empty(const void *, const void *) noexcept
{ /* nothing to assign */
}
};
template <class T, bool nothrow> struct strong_swap_impl
Expand Down Expand Up @@ -3146,7 +3172,7 @@ namespace detail
empty_type _empty2;
_error_type_ _error;
};
#if __cplusplus >= 202000L || _HAS_CXX20
#if __cplusplus >= 202000 || _HAS_CXX20
constexpr
#endif
value_storage_nontrivial() noexcept
Expand All @@ -3156,7 +3182,7 @@ namespace detail
}
value_storage_nontrivial &operator=(const value_storage_nontrivial &) = default; // if reaches here, copy assignment is trivial
value_storage_nontrivial &operator=(value_storage_nontrivial &&) = default; // NOLINT if reaches here, move assignment is trivial
#if __cplusplus >= 202000L || _HAS_CXX20
#if __cplusplus >= 202000 || _HAS_CXX20
constexpr
#endif
value_storage_nontrivial(value_storage_nontrivial &&o) noexcept(
Expand All @@ -3173,7 +3199,7 @@ namespace detail
_status = o._status;
o._status.set_have_moved_from(true);
}
#if __cplusplus >= 202000L || _HAS_CXX20
#if __cplusplus >= 202000 || _HAS_CXX20
constexpr
#endif
value_storage_nontrivial(const value_storage_nontrivial &o) noexcept(
Expand All @@ -3189,7 +3215,7 @@ namespace detail
}
_status = o._status;
}
#if __cplusplus >= 202000L || _HAS_CXX20
#if __cplusplus >= 202000 || _HAS_CXX20
constexpr
#endif
explicit value_storage_nontrivial(status_bitfield_type status)
Expand Down Expand Up @@ -3349,7 +3375,7 @@ namespace detail
_status = o._status;
o._status.set_have_moved_from(true);
}
#if __cplusplus >= 202000L || _HAS_CXX20
#if __cplusplus >= 202000 || _HAS_CXX20
constexpr
#endif
~value_storage_nontrivial() noexcept(std::is_nothrow_destructible<_value_type_>::value &&std::is_nothrow_destructible<_error_type_>::value)
Expand All @@ -3371,7 +3397,7 @@ namespace detail
this->_status.set_have_error(false);
}
}
#if __cplusplus >= 202000L || _HAS_CXX20
#if __cplusplus >= 202000 || _HAS_CXX20
constexpr
#endif
void
Expand Down Expand Up @@ -3568,14 +3594,15 @@ namespace detail
value_storage_nontrivial_move_assignment(value_storage_nontrivial_move_assignment &&) = default; // NOLINT
value_storage_nontrivial_move_assignment &operator=(const value_storage_nontrivial_move_assignment &o) = default;
~value_storage_nontrivial_move_assignment() = default;
#if __cplusplus >= 202000L || _HAS_CXX20
#if __cplusplus >= 202000 || _HAS_CXX20
constexpr
#endif
value_storage_nontrivial_move_assignment &
operator=(value_storage_nontrivial_move_assignment &&o) noexcept(
std::is_nothrow_move_assignable<value_type>::value &&std::is_nothrow_move_assignable<error_type>::value &&noexcept(move_assign_to_empty<value_type>(
static_cast<value_type *>(nullptr), std::declval<value_type>())) &&noexcept(move_assign_to_empty<error_type>(static_cast<error_type *>(nullptr),
std::declval<error_type>()))) // NOLINT
static_cast<value_type *>(nullptr),
static_cast<value_type *>(nullptr))) &&noexcept(move_assign_to_empty<error_type>(static_cast<error_type *>(nullptr),
static_cast<error_type *>(nullptr)))) // NOLINT
{
using _value_type_ = typename Base::_value_type_;
using _error_type_ = typename Base::_error_type_;
Expand Down Expand Up @@ -3611,7 +3638,7 @@ namespace detail
}
if(!this->_status.have_value() && !this->_status.have_error() && o._status.have_value())
{
move_assign_to_empty<_value_type_>(&this->_value, static_cast<_value_type_ &&>(o._value));
move_assign_to_empty<_value_type_>(&this->_value, &o._value);
this->_status = o._status;
o._status.set_have_moved_from(true);
return *this;
Expand All @@ -3628,7 +3655,7 @@ namespace detail
}
if(!this->_status.have_value() && !this->_status.have_error() && o._status.have_error())
{
move_assign_to_empty<_error_type_>(&this->_error, static_cast<_error_type_ &&>(o._error));
move_assign_to_empty<_error_type_>(&this->_error, &o._error);
this->_status = o._status;
o._status.set_have_moved_from(true);
return *this;
Expand All @@ -3639,7 +3666,7 @@ namespace detail
{
this->_value.~_value_type_(); // NOLINT
}
move_assign_to_empty<_error_type_>(&this->_error, static_cast<_error_type_ &&>(o._error));
move_assign_to_empty<_error_type_>(&this->_error, &o._error);
this->_status = o._status;
o._status.set_have_moved_from(true);
return *this;
Expand All @@ -3650,7 +3677,7 @@ namespace detail
{
this->_error.~_error_type_(); // NOLINT
}
move_assign_to_empty<_value_type_>(&this->_value, static_cast<_value_type_ &&>(o._value));
move_assign_to_empty<_value_type_>(&this->_value, &o._value);
this->_status = o._status;
o._status.set_have_moved_from(true);
return *this;
Expand All @@ -3669,14 +3696,14 @@ namespace detail
value_storage_nontrivial_copy_assignment(value_storage_nontrivial_copy_assignment &&) = default; // NOLINT
value_storage_nontrivial_copy_assignment &operator=(value_storage_nontrivial_copy_assignment &&o) = default; // NOLINT
~value_storage_nontrivial_copy_assignment() = default;
#if __cplusplus >= 202000L || _HAS_CXX20
#if __cplusplus >= 202000 || _HAS_CXX20
constexpr
#endif
value_storage_nontrivial_copy_assignment &
operator=(const value_storage_nontrivial_copy_assignment &o) noexcept(
std::is_nothrow_copy_assignable<value_type>::value &&std::is_nothrow_copy_assignable<error_type>::value &&noexcept(copy_assign_to_empty<value_type>(
static_cast<value_type *>(nullptr), std::declval<value_type>())) &&noexcept(copy_assign_to_empty<error_type>(static_cast<error_type *>(nullptr),
std::declval<error_type>())))
static_cast<value_type *>(nullptr), static_cast<value_type *>(nullptr))) &&noexcept(copy_assign_to_empty<error_type>(static_cast<error_type *>(nullptr),
static_cast<error_type *>(nullptr))))
{
using _value_type_ = typename Base::_value_type_;
using _error_type_ = typename Base::_error_type_;
Expand Down Expand Up @@ -3708,7 +3735,7 @@ namespace detail
}
if(!this->_status.have_value() && !this->_status.have_error() && o._status.have_value())
{
copy_assign_to_empty<_value_type_>(&this->_value, o._value);
copy_assign_to_empty<_value_type_>(&this->_value, &o._value);
this->_status = o._status;
return *this;
}
Expand All @@ -3723,7 +3750,7 @@ namespace detail
}
if(!this->_status.have_value() && !this->_status.have_error() && o._status.have_error())
{
copy_assign_to_empty<_error_type_>(&this->_error, o._error);
copy_assign_to_empty<_error_type_>(&this->_error, &o._error);
this->_status = o._status;
return *this;
}
Expand All @@ -3733,7 +3760,7 @@ namespace detail
{
this->_value.~_value_type_(); // NOLINT
}
copy_assign_to_empty<_error_type_>(&this->_error, o._error);
copy_assign_to_empty<_error_type_>(&this->_error, &o._error);
this->_status = o._status;
return *this;
}
Expand All @@ -3743,7 +3770,7 @@ namespace detail
{
this->_error.~_error_type_(); // NOLINT
}
copy_assign_to_empty<_value_type_>(&this->_value, o._value);
copy_assign_to_empty<_value_type_>(&this->_value, &o._value);
this->_status = o._status;
return *this;
}
Expand Down Expand Up @@ -7075,7 +7102,7 @@ SIGNATURE NOT RECOGNISED
};
// C++ 20 operator== rewriting should take care of this for us, indeed
// if we don't disable it, we cause Concept recursion to infinity!
#if __cplusplus < 202000L && !_HAS_CXX20
#if __cplusplus < 202000 && !_HAS_CXX20
/*! AWAITING HUGO JSON CONVERSION TOOL
SIGNATURE NOT RECOGNISED
*/
Expand Down Expand Up @@ -7808,7 +7835,7 @@ OUTCOME_V2_NAMESPACE_END
#define _OUTCOME_TRY_OVERLOAD_GLUE(x, y) x y
#define _OUTCOME_TRY_CALL_OVERLOAD(name, ...) _OUTCOME_TRY_OVERLOAD_GLUE(_OUTCOME_TRY_OVERLOAD_MACRO(name, _OUTCOME_TRY_COUNT_ARGS_MAX8(__VA_ARGS__)), (__VA_ARGS__))
#ifndef OUTCOME_TRY_LIKELY_IF
#if (__cplusplus >= 202000L || _HAS_CXX20) && (!defined(__clang__) || __clang_major__ >= 12) && (!defined(__GNUC__) || defined(__clang__) || __GNUC__ >= 9)
#if (__cplusplus >= 202000 || _HAS_CXX20) && (!defined(__clang__) || __clang_major__ >= 12) && (!defined(__GNUC__) || defined(__clang__) || __GNUC__ >= 9)
#define OUTCOME_TRY_LIKELY_IF(...) if(__VA_ARGS__) [[likely]]
#elif defined(__clang__) || defined(__GNUC__)
#define OUTCOME_TRY_LIKELY_IF(...) if(__builtin_expect(!!(__VA_ARGS__), true))
Expand Down
149 changes: 119 additions & 30 deletions test/tests/issue0259.cpp
Expand Up @@ -21,7 +21,7 @@ Distributed under the Boost Software License, Version 1.0.
http://www.boost.org/LICENSE_1_0.txt)
*/

#include "../../include/outcome/result.hpp"
#include "../../include/outcome/outcome.hpp"

#include "quickcpplib/boost/test/unit_test.hpp"

Expand Down Expand Up @@ -72,33 +72,122 @@ BOOST_OUTCOME_AUTO_TEST_CASE(issues / 0259 / test, "move assignable is not calcu
~NonDefaultConstructibleCopyAssignable() = default;
};

OUTCOME_V2_NAMESPACE::result<DefaultConstructibleMoveAssignable> test1(OUTCOME_V2_NAMESPACE::success(5)), test1a(OUTCOME_V2_NAMESPACE::success(6));
test1 = std::move(test1a);
static_assert(!std::is_copy_constructible<OUTCOME_V2_NAMESPACE::result<DefaultConstructibleMoveAssignable>>::value, "");
static_assert(!std::is_move_constructible<OUTCOME_V2_NAMESPACE::result<DefaultConstructibleMoveAssignable>>::value, "");
static_assert(!std::is_copy_assignable<OUTCOME_V2_NAMESPACE::result<DefaultConstructibleMoveAssignable>>::value, "");
static_assert(std::is_move_assignable<OUTCOME_V2_NAMESPACE::result<DefaultConstructibleMoveAssignable>>::value, "");
static_assert(std::is_destructible<OUTCOME_V2_NAMESPACE::result<DefaultConstructibleMoveAssignable>>::value, "");

OUTCOME_V2_NAMESPACE::result<DefaultConstructibleCopyAssignable> test2(OUTCOME_V2_NAMESPACE::success(5)), test2a(OUTCOME_V2_NAMESPACE::success(6));
test2 = test2a;
static_assert(!std::is_copy_constructible<OUTCOME_V2_NAMESPACE::result<DefaultConstructibleCopyAssignable>>::value, "");
static_assert(!std::is_move_constructible<OUTCOME_V2_NAMESPACE::result<DefaultConstructibleCopyAssignable>>::value, "");
static_assert(std::is_copy_assignable<OUTCOME_V2_NAMESPACE::result<DefaultConstructibleCopyAssignable>>::value, "");
static_assert(std::is_move_assignable<OUTCOME_V2_NAMESPACE::result<DefaultConstructibleCopyAssignable>>::value, "");
static_assert(std::is_destructible<OUTCOME_V2_NAMESPACE::result<DefaultConstructibleCopyAssignable>>::value, "");

OUTCOME_V2_NAMESPACE::result<NonDefaultConstructibleMoveAssignable> test3(OUTCOME_V2_NAMESPACE::success(5)), test3a(OUTCOME_V2_NAMESPACE::success(6));
static_assert(!std::is_copy_constructible<OUTCOME_V2_NAMESPACE::result<NonDefaultConstructibleMoveAssignable>>::value, "");
static_assert(!std::is_move_constructible<OUTCOME_V2_NAMESPACE::result<NonDefaultConstructibleMoveAssignable>>::value, "");
static_assert(!std::is_copy_assignable<OUTCOME_V2_NAMESPACE::result<NonDefaultConstructibleMoveAssignable>>::value, "");
static_assert(!std::is_move_assignable<OUTCOME_V2_NAMESPACE::result<NonDefaultConstructibleMoveAssignable>>::value, "");
static_assert(std::is_destructible<OUTCOME_V2_NAMESPACE::result<NonDefaultConstructibleMoveAssignable>>::value, "");

OUTCOME_V2_NAMESPACE::result<NonDefaultConstructibleCopyAssignable> test4(OUTCOME_V2_NAMESPACE::success(5)), test4a(OUTCOME_V2_NAMESPACE::success(6));
static_assert(!std::is_copy_constructible<OUTCOME_V2_NAMESPACE::result<NonDefaultConstructibleCopyAssignable>>::value, "");
static_assert(!std::is_move_constructible<OUTCOME_V2_NAMESPACE::result<NonDefaultConstructibleCopyAssignable>>::value, "");
static_assert(!std::is_copy_assignable<OUTCOME_V2_NAMESPACE::result<NonDefaultConstructibleCopyAssignable>>::value, "");
static_assert(!std::is_move_assignable<OUTCOME_V2_NAMESPACE::result<NonDefaultConstructibleCopyAssignable>>::value, "");
static_assert(std::is_destructible<OUTCOME_V2_NAMESPACE::result<NonDefaultConstructibleCopyAssignable>>::value, "");
{
using type = OUTCOME_V2_NAMESPACE::result<DefaultConstructibleMoveAssignable>;
type test1(OUTCOME_V2_NAMESPACE::success(5)), test1a(OUTCOME_V2_NAMESPACE::success(6));
test1 = std::move(test1a);
static_assert(!std::is_copy_constructible<type>::value, "");
static_assert(!std::is_move_constructible<type>::value, "");
static_assert(!std::is_copy_assignable<type>::value, "");
static_assert(std::is_move_assignable<type>::value, "");
static_assert(std::is_destructible<type>::value, "");
}
{
using type = OUTCOME_V2_NAMESPACE::result<DefaultConstructibleCopyAssignable>;
type test1(OUTCOME_V2_NAMESPACE::success(5)), test1a(OUTCOME_V2_NAMESPACE::success(6));
test1 = std::move(test1a);
static_assert(!std::is_copy_constructible<type>::value, "");
static_assert(!std::is_move_constructible<type>::value, "");
static_assert(std::is_copy_assignable<type>::value, "");
static_assert(std::is_move_assignable<type>::value, "");
static_assert(std::is_destructible<type>::value, "");
}
{
using type = OUTCOME_V2_NAMESPACE::result<NonDefaultConstructibleMoveAssignable>;
type test1(OUTCOME_V2_NAMESPACE::success(5)), test1a(OUTCOME_V2_NAMESPACE::success(6));
static_assert(!std::is_copy_constructible<type>::value, "");
static_assert(!std::is_move_constructible<type>::value, "");
static_assert(!std::is_copy_assignable<type>::value, "");
static_assert(!std::is_move_assignable<type>::value, "");
static_assert(std::is_destructible<type>::value, "");
}
{
using type = OUTCOME_V2_NAMESPACE::result<NonDefaultConstructibleCopyAssignable>;
type test1(OUTCOME_V2_NAMESPACE::success(5)), test1a(OUTCOME_V2_NAMESPACE::success(6));
static_assert(!std::is_copy_constructible<type>::value, "");
static_assert(!std::is_move_constructible<type>::value, "");
static_assert(!std::is_copy_assignable<type>::value, "");
static_assert(!std::is_move_assignable<type>::value, "");
static_assert(std::is_destructible<type>::value, "");
}
{
using type = OUTCOME_V2_NAMESPACE::result<void, DefaultConstructibleMoveAssignable>;
type test1(OUTCOME_V2_NAMESPACE::failure(5)), test1a(OUTCOME_V2_NAMESPACE::failure(6));
test1 = std::move(test1a);
static_assert(!std::is_copy_constructible<type>::value, "");
static_assert(!std::is_move_constructible<type>::value, "");
static_assert(!std::is_copy_assignable<type>::value, "");
static_assert(std::is_move_assignable<type>::value, "");
static_assert(std::is_destructible<type>::value, "");
}
{
using type = OUTCOME_V2_NAMESPACE::result<void, DefaultConstructibleCopyAssignable>;
type test1(OUTCOME_V2_NAMESPACE::failure(5)), test1a(OUTCOME_V2_NAMESPACE::failure(6));
test1 = std::move(test1a);
static_assert(!std::is_copy_constructible<type>::value, "");
static_assert(!std::is_move_constructible<type>::value, "");
static_assert(std::is_copy_assignable<type>::value, "");
static_assert(std::is_move_assignable<type>::value, "");
static_assert(std::is_destructible<type>::value, "");
}
{
using type = OUTCOME_V2_NAMESPACE::result<DefaultConstructibleMoveAssignable, void>;
type test1(OUTCOME_V2_NAMESPACE::success(5)), test1a(OUTCOME_V2_NAMESPACE::success(6));
test1 = std::move(test1a);
static_assert(!std::is_copy_constructible<type>::value, "");
static_assert(!std::is_move_constructible<type>::value, "");
static_assert(!std::is_copy_assignable<type>::value, "");
static_assert(std::is_move_assignable<type>::value, "");
static_assert(std::is_destructible<type>::value, "");
}
{
using type = OUTCOME_V2_NAMESPACE::result<DefaultConstructibleCopyAssignable, void>;
type test1(OUTCOME_V2_NAMESPACE::success(5)), test1a(OUTCOME_V2_NAMESPACE::success(6));
test1 = std::move(test1a);
static_assert(!std::is_copy_constructible<type>::value, "");
static_assert(!std::is_move_constructible<type>::value, "");
static_assert(std::is_copy_assignable<type>::value, "");
static_assert(std::is_move_assignable<type>::value, "");
static_assert(std::is_destructible<type>::value, "");
}
{
using type = OUTCOME_V2_NAMESPACE::outcome<int, double, DefaultConstructibleMoveAssignable>;
type test1(OUTCOME_V2_NAMESPACE::success(5)), test1a(OUTCOME_V2_NAMESPACE::success(6));
test1 = std::move(test1a);
static_assert(!std::is_copy_constructible<type>::value, "");
static_assert(!std::is_move_constructible<type>::value, "");
static_assert(!std::is_copy_assignable<type>::value, "");
static_assert(std::is_move_assignable<type>::value, "");
static_assert(std::is_destructible<type>::value, "");
}
{
using type = OUTCOME_V2_NAMESPACE::outcome<int, double, DefaultConstructibleCopyAssignable>;
type test1(OUTCOME_V2_NAMESPACE::success(5)), test1a(OUTCOME_V2_NAMESPACE::success(6));
test1 = std::move(test1a);
static_assert(!std::is_copy_constructible<type>::value, "");
static_assert(!std::is_move_constructible<type>::value, "");
static_assert(std::is_copy_assignable<type>::value, "");
static_assert(std::is_move_assignable<type>::value, "");
static_assert(std::is_destructible<type>::value, "");
}
{
using type = OUTCOME_V2_NAMESPACE::outcome<void, void, DefaultConstructibleMoveAssignable>;
type test1(OUTCOME_V2_NAMESPACE::success()), test1a(OUTCOME_V2_NAMESPACE::success());
test1 = std::move(test1a);
static_assert(!std::is_copy_constructible<type>::value, "");
static_assert(!std::is_move_constructible<type>::value, "");
static_assert(!std::is_copy_assignable<type>::value, "");
static_assert(std::is_move_assignable<type>::value, "");
static_assert(std::is_destructible<type>::value, "");
}
{
using type = OUTCOME_V2_NAMESPACE::outcome<void, void, DefaultConstructibleCopyAssignable>;
type test1(OUTCOME_V2_NAMESPACE::success()), test1a(OUTCOME_V2_NAMESPACE::success());
test1 = std::move(test1a);
static_assert(!std::is_copy_constructible<type>::value, "");
static_assert(!std::is_move_constructible<type>::value, "");
static_assert(std::is_copy_assignable<type>::value, "");
static_assert(std::is_move_assignable<type>::value, "");
static_assert(std::is_destructible<type>::value, "");
}
}