1//===----------------------------------------------------------------------===// 2// 3// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 4// See https://llvm.org/LICENSE.txt for license information. 5// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 6// 7//===----------------------------------------------------------------------===// 8 9#ifndef _LIBCPP___TYPE_TRAITS_IS_SWAPPABLE_H 10#define _LIBCPP___TYPE_TRAITS_IS_SWAPPABLE_H 11 12#include <__config> 13#include <__type_traits/add_lvalue_reference.h> 14#include <__type_traits/conditional.h> 15#include <__type_traits/enable_if.h> 16#include <__type_traits/is_move_assignable.h> 17#include <__type_traits/is_move_constructible.h> 18#include <__type_traits/is_nothrow_move_assignable.h> 19#include <__type_traits/is_nothrow_move_constructible.h> 20#include <__type_traits/is_referenceable.h> 21#include <__type_traits/is_same.h> 22#include <__type_traits/is_void.h> 23#include <__type_traits/nat.h> 24#include <__utility/declval.h> 25#include <cstddef> 26 27#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) 28# pragma GCC system_header 29#endif 30 31_LIBCPP_BEGIN_NAMESPACE_STD 32 33template <class _Tp> struct __is_swappable; 34template <class _Tp> struct __is_nothrow_swappable; 35 36 37#ifndef _LIBCPP_CXX03_LANG 38template <class _Tp> 39using __swap_result_t = typename enable_if<is_move_constructible<_Tp>::value && is_move_assignable<_Tp>::value>::type; 40#else 41template <class> 42using __swap_result_t = void; 43#endif 44 45template <class _Tp> 46inline _LIBCPP_INLINE_VISIBILITY 47_LIBCPP_CONSTEXPR_SINCE_CXX20 __swap_result_t<_Tp> 48swap(_Tp& __x, _Tp& __y) _NOEXCEPT_(is_nothrow_move_constructible<_Tp>::value && 49 is_nothrow_move_assignable<_Tp>::value); 50 51template<class _Tp, size_t _Np> 52inline _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_SINCE_CXX20 53typename enable_if< 54 __is_swappable<_Tp>::value 55>::type 56swap(_Tp (&__a)[_Np], _Tp (&__b)[_Np]) _NOEXCEPT_(__is_nothrow_swappable<_Tp>::value); 57 58namespace __detail 59{ 60// ALL generic swap overloads MUST already have a declaration available at this point. 61 62template <class _Tp, class _Up = _Tp, 63 bool _NotVoid = !is_void<_Tp>::value && !is_void<_Up>::value> 64struct __swappable_with 65{ 66 template <class _LHS, class _RHS> 67 static decltype(swap(std::declval<_LHS>(), std::declval<_RHS>())) 68 __test_swap(int); 69 template <class, class> 70 static __nat __test_swap(long); 71 72 // Extra parens are needed for the C++03 definition of decltype. 73 typedef decltype((__test_swap<_Tp, _Up>(0))) __swap1; 74 typedef decltype((__test_swap<_Up, _Tp>(0))) __swap2; 75 76 static const bool value = _IsNotSame<__swap1, __nat>::value 77 && _IsNotSame<__swap2, __nat>::value; 78}; 79 80template <class _Tp, class _Up> 81struct __swappable_with<_Tp, _Up, false> : false_type {}; 82 83template <class _Tp, class _Up = _Tp, bool _Swappable = __swappable_with<_Tp, _Up>::value> 84struct __nothrow_swappable_with { 85 static const bool value = 86#ifndef _LIBCPP_HAS_NO_NOEXCEPT 87 noexcept(swap(std::declval<_Tp>(), std::declval<_Up>())) 88 && noexcept(swap(std::declval<_Up>(), std::declval<_Tp>())); 89#else 90 false; 91#endif 92}; 93 94template <class _Tp, class _Up> 95struct __nothrow_swappable_with<_Tp, _Up, false> : false_type {}; 96 97} // namespace __detail 98 99template <class _Tp> 100struct __is_swappable 101 : public integral_constant<bool, __detail::__swappable_with<_Tp&>::value> 102{ 103}; 104 105template <class _Tp> 106struct __is_nothrow_swappable 107 : public integral_constant<bool, __detail::__nothrow_swappable_with<_Tp&>::value> 108{ 109}; 110 111#if _LIBCPP_STD_VER > 14 112 113template <class _Tp, class _Up> 114struct _LIBCPP_TEMPLATE_VIS is_swappable_with 115 : public integral_constant<bool, __detail::__swappable_with<_Tp, _Up>::value> 116{ 117}; 118 119template <class _Tp> 120struct _LIBCPP_TEMPLATE_VIS is_swappable 121 : public __conditional_t< 122 __libcpp_is_referenceable<_Tp>::value, 123 is_swappable_with< 124 __add_lvalue_reference_t<_Tp>, 125 __add_lvalue_reference_t<_Tp> >, 126 false_type 127 > 128{ 129}; 130 131template <class _Tp, class _Up> 132struct _LIBCPP_TEMPLATE_VIS is_nothrow_swappable_with 133 : public integral_constant<bool, __detail::__nothrow_swappable_with<_Tp, _Up>::value> 134{ 135}; 136 137template <class _Tp> 138struct _LIBCPP_TEMPLATE_VIS is_nothrow_swappable 139 : public __conditional_t< 140 __libcpp_is_referenceable<_Tp>::value, 141 is_nothrow_swappable_with< 142 __add_lvalue_reference_t<_Tp>, 143 __add_lvalue_reference_t<_Tp> >, 144 false_type 145 > 146{ 147}; 148 149template <class _Tp, class _Up> 150inline constexpr bool is_swappable_with_v = is_swappable_with<_Tp, _Up>::value; 151 152template <class _Tp> 153inline constexpr bool is_swappable_v = is_swappable<_Tp>::value; 154 155template <class _Tp, class _Up> 156inline constexpr bool is_nothrow_swappable_with_v = is_nothrow_swappable_with<_Tp, _Up>::value; 157 158template <class _Tp> 159inline constexpr bool is_nothrow_swappable_v = is_nothrow_swappable<_Tp>::value; 160 161#endif // _LIBCPP_STD_VER > 14 162 163_LIBCPP_END_NAMESPACE_STD 164 165#endif // _LIBCPP___TYPE_TRAITS_IS_SWAPPABLE_H 166