mirror of
https://github.com/TartanLlama/optional.git
synced 2025-06-25 00:51:37 +02:00
Better is_swappable impl
This commit is contained in:
66
optional.hpp
66
optional.hpp
@ -108,21 +108,63 @@ namespace tl {
|
||||
!std::is_assignable<T&, const optional<U>&&>::value
|
||||
>;
|
||||
|
||||
//TODO improve
|
||||
template <class T, class=void>
|
||||
struct is_swappable : std::false_type{};
|
||||
|
||||
template <class T>
|
||||
struct is_swappable<T,void_t<decltype(swap(std::declval<T>(), std::declval<T>()))>>
|
||||
: std::true_type{};
|
||||
// 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 {};
|
||||
|
||||
//TODO improve
|
||||
template <class T, class=void>
|
||||
struct is_nothrow_swappable : std::false_type{};
|
||||
template<class T> tag swap(T&, T&);
|
||||
template<class T, std::size_t N> tag swap(T (&a)[N], T (&b)[N]);
|
||||
|
||||
template <class T>
|
||||
struct is_nothrow_swappable<T,void_t<decltype(swap(std::declval<T>(), std::declval<T>()))>>
|
||||
: std::true_type{};
|
||||
// helper functions to test if an unqualified swap is possible, and if it becomes std::swap
|
||||
template<class, class> std::false_type can_swap(...) noexcept(false);
|
||||
template<class T, class U, class = decltype(swap(std::declval<T&>(), std::declval<U&>()))>
|
||||
std::true_type can_swap(int) noexcept(
|
||||
noexcept(swap(std::declval<T&>(), std::declval<U&>()))
|
||||
);
|
||||
|
||||
template<class, class> std::false_type uses_std(...);
|
||||
template<class T, class U>
|
||||
std::is_same<decltype(swap(std::declval<T&>(), std::declval<U&>())), tag> uses_std(int);
|
||||
|
||||
template<class T>
|
||||
struct is_std_swap_noexcept : std::integral_constant<bool,
|
||||
std::is_nothrow_move_constructible<T>::value &&
|
||||
std::is_nothrow_move_assignable<T>::value
|
||||
> { };
|
||||
|
||||
template<class T, std::size_t N>
|
||||
struct is_std_swap_noexcept<T[N]> : is_std_swap_noexcept<T> { };
|
||||
|
||||
template<class T, class U>
|
||||
struct is_adl_swap_noexcept : std::integral_constant<bool, noexcept(can_swap<T, U>(0))> { };
|
||||
}
|
||||
|
||||
template<class T, class U = T>
|
||||
struct is_swappable : std::integral_constant<bool,
|
||||
decltype(detail::swap_adl_tests::can_swap<T, U>(0))::value &&
|
||||
(!decltype(detail::swap_adl_tests::uses_std<T, U>(0))::value ||
|
||||
(std::is_move_assignable<T>::value && std::is_move_constructible<T>::value))
|
||||
> {};
|
||||
|
||||
template<class T, std::size_t N>
|
||||
struct is_swappable<T[N], T[N]> : std::integral_constant<bool,
|
||||
decltype(detail::swap_adl_tests::can_swap<T[N], T[N]>(0))::value &&
|
||||
(!decltype(detail::swap_adl_tests::uses_std<T[N], T[N]>(0))::value ||
|
||||
is_swappable<T, T>::value)
|
||||
> {};
|
||||
|
||||
template<class T, class U = T>
|
||||
struct is_nothrow_swappable : std::integral_constant<bool,
|
||||
is_swappable<T, U>::value && (
|
||||
(decltype(detail::swap_adl_tests::uses_std<T, U>(0))::value &&
|
||||
detail::swap_adl_tests::is_std_swap_noexcept<T>::value)
|
||||
||
|
||||
(!decltype(detail::swap_adl_tests::uses_std<T, U>(0))::value &&
|
||||
detail::swap_adl_tests::is_adl_swap_noexcept<T, U>::value)
|
||||
)
|
||||
> {};
|
||||
}
|
||||
|
||||
// [optional.nullopt], no-value state indicator
|
||||
|
Reference in New Issue
Block a user