But bugs aside, this is done by testing is_nothrow_swappable_v<T>. Or, before C++17, with a construction similar to this:
template< typename T > T& make_lvalue() noexcept;
constexpr bool is_nothrow_swappable = noexcept(swap(make_lvalue<T>(), make_lvalue<T>()));
Outcome did this in v2.1.0. It didn't work right, swap() wasn't always instanceable at the point of parsing basic_result. I replaced it with an exact replica of std::is_nothrow_swappable, and now it works properly in v2.1.1.
In other words, how can it make sense that swap<T> be noexcept without considering the specific type T?
Robert, you may find studying Outcome's strong_swap() of interest. Ref page: https://ned14.github.io/outcome/reference/functions/strong_swap/ Implementation: https://github.com/ned14/outcome/blob/develop/include/outcome/detail/value_s... tldr; implementing the strong guarantee is much harder than it looks, and actually offers surprisingly little benefit in practice. It's also a pain to implement without making constexpr puke, at least in C++ 14. All in all, the weak guarantee is likely plenty good for almost everybody almost all of the time. Niall