diff options
author | Eric Fiselier <eric@efcs.ca> | 2016-04-21 23:38:59 +0000 |
---|---|---|
committer | Eric Fiselier <eric@efcs.ca> | 2016-04-21 23:38:59 +0000 |
commit | f07dd8d0a925dd8cbde7bb6198c1ba92446110ea (patch) | |
tree | 581032748ea2b3640d2e7f033f2e651eb67416bd /libcxx/include | |
parent | c89755e4cbad7a46d747f3b2d49c50a80855a801 (diff) | |
download | bcm5719-llvm-f07dd8d0a925dd8cbde7bb6198c1ba92446110ea.tar.gz bcm5719-llvm-f07dd8d0a925dd8cbde7bb6198c1ba92446110ea.zip |
Add is_swappable/is_nothrow_swappable traits
llvm-svn: 267079
Diffstat (limited to 'libcxx/include')
-rw-r--r-- | libcxx/include/algorithm | 2 | ||||
-rw-r--r-- | libcxx/include/array | 16 | ||||
-rw-r--r-- | libcxx/include/map | 4 | ||||
-rw-r--r-- | libcxx/include/memory | 5 | ||||
-rw-r--r-- | libcxx/include/queue | 16 | ||||
-rw-r--r-- | libcxx/include/stack | 7 | ||||
-rw-r--r-- | libcxx/include/type_traits | 112 | ||||
-rw-r--r-- | libcxx/include/utility | 13 |
8 files changed, 133 insertions, 42 deletions
diff --git a/libcxx/include/algorithm b/libcxx/include/algorithm index 2ea1daed94f..7a6db7abd26 100644 --- a/libcxx/include/algorithm +++ b/libcxx/include/algorithm @@ -630,7 +630,7 @@ template <class BidirectionalIterator, class Compare> #include <initializer_list> #include <type_traits> #include <cstring> -#include <utility> +#include <utility> // needed to provide swap_ranges. #include <memory> #include <iterator> #include <cstddef> diff --git a/libcxx/include/array b/libcxx/include/array index f0350ea216e..719286d52ea 100644 --- a/libcxx/include/array +++ b/libcxx/include/array @@ -34,7 +34,7 @@ struct array // No explicit construct/copy/destroy for aggregate type void fill(const T& u); - void swap(array& a) noexcept(noexcept(swap(declval<T&>(), declval<T&>()))); + void swap(array& a) noexcept(is_nothrow_swappable_v<T>); // iterators: iterator begin() noexcept; @@ -141,8 +141,15 @@ struct _LIBCPP_TYPE_VIS_ONLY array _LIBCPP_INLINE_VISIBILITY void fill(const value_type& __u) {_VSTD::fill_n(__elems_, _Size, __u);} _LIBCPP_INLINE_VISIBILITY - void swap(array& __a) _NOEXCEPT_(__is_nothrow_swappable<_Tp>::value) - {_VSTD::swap_ranges(__elems_, __elems_ + _Size, __a.__elems_);} + void swap(array& __a) _NOEXCEPT_(_Size == 0 || __is_nothrow_swappable<_Tp>::value) + { __swap_dispatch((std::integral_constant<bool, _Size == 0>()), __a); } + + _LIBCPP_INLINE_VISIBILITY + void __swap_dispatch(std::true_type, array&) {} + + _LIBCPP_INLINE_VISIBILITY + void __swap_dispatch(std::false_type, array& __a) + { _VSTD::swap_ranges(__elems_, __elems_ + _Size, __a.__elems_);} // iterators: _LIBCPP_INLINE_VISIBILITY @@ -276,11 +283,12 @@ template <class _Tp, size_t _Size> inline _LIBCPP_INLINE_VISIBILITY typename enable_if < + _Size == 0 || __is_swappable<_Tp>::value, void >::type swap(array<_Tp, _Size>& __x, array<_Tp, _Size>& __y) - _NOEXCEPT_(__is_nothrow_swappable<_Tp>::value) + _NOEXCEPT_(noexcept(__x.swap(__y))) { __x.swap(__y); } diff --git a/libcxx/include/map b/libcxx/include/map index d04b803ce67..8dc84e73cbf 100644 --- a/libcxx/include/map +++ b/libcxx/include/map @@ -162,7 +162,7 @@ public: void swap(map& m) noexcept(allocator_traits<allocator_type>::is_always_equal::value && - __is_nothrow_swappable<key_compare>::value); // C++17 + is_nothrow_swappable<key_compare>::value); // C++17 // observers: allocator_type get_allocator() const noexcept; @@ -357,7 +357,7 @@ public: void swap(multimap& m) noexcept(allocator_traits<allocator_type>::is_always_equal::value && - __is_nothrow_swappable<key_compare>::value); // C++17 + is_nothrow_swappable<key_compare>::value); // C++17 // observers: allocator_type get_allocator() const noexcept; diff --git a/libcxx/include/memory b/libcxx/include/memory index e59fd5d38a4..788830329d6 100644 --- a/libcxx/include/memory +++ b/libcxx/include/memory @@ -2974,7 +2974,10 @@ private: template <class _Tp, class _Dp> inline _LIBCPP_INLINE_VISIBILITY -void +typename enable_if< + __is_swappable<_Dp>::value, + void +>::type swap(unique_ptr<_Tp, _Dp>& __x, unique_ptr<_Tp, _Dp>& __y) _NOEXCEPT {__x.swap(__y);} template <class _T1, class _D1, class _T2, class _D2> diff --git a/libcxx/include/queue b/libcxx/include/queue index 81b83a7701e..2509b93ede6 100644 --- a/libcxx/include/queue +++ b/libcxx/include/queue @@ -66,7 +66,7 @@ public: template <class... Args> void emplace(Args&&... args); void pop(); - void swap(queue& q) noexcept(noexcept(swap(c, q.c))); + void swap(queue& q) noexcept(is_nothrow_swappable_v<Container>) }; template <class T, class Container> @@ -153,7 +153,8 @@ public: void pop(); void swap(priority_queue& q) - noexcept(noexcept(swap(c, q.c)) && noexcept(swap(comp.q.comp))); + noexcept(is_nothrow_swappable_v<Container> && + is_nothrow_swappable_v<Comp>) }; template <class T, class Container, class Compare> @@ -369,7 +370,10 @@ operator<=(const queue<_Tp, _Container>& __x,const queue<_Tp, _Container>& __y) template <class _Tp, class _Container> inline _LIBCPP_INLINE_VISIBILITY -void +typename enable_if< + __is_swappable<_Container>::value, + void +>::type swap(queue<_Tp, _Container>& __x, queue<_Tp, _Container>& __y) _NOEXCEPT_(_NOEXCEPT_(__x.swap(__y))) { @@ -700,7 +704,11 @@ priority_queue<_Tp, _Container, _Compare>::swap(priority_queue& __q) template <class _Tp, class _Container, class _Compare> inline _LIBCPP_INLINE_VISIBILITY -void +typename enable_if< + __is_swappable<_Container>::value + && __is_swappable<_Compare>::value, + void +>::type swap(priority_queue<_Tp, _Container, _Compare>& __x, priority_queue<_Tp, _Container, _Compare>& __y) _NOEXCEPT_(_NOEXCEPT_(__x.swap(__y))) diff --git a/libcxx/include/stack b/libcxx/include/stack index 64fd65215d9..48b3b0d16ec 100644 --- a/libcxx/include/stack +++ b/libcxx/include/stack @@ -58,7 +58,7 @@ public: template <class... Args> void emplace(Args&&... args); void pop(); - void swap(stack& c) noexcept(noexcept(swap(c, q.c))); + void swap(stack& c) noexcept(is_nothrow_swappable_v<Container>) }; template <class T, class Container> @@ -275,7 +275,10 @@ operator<=(const stack<_Tp, _Container>& __x, const stack<_Tp, _Container>& __y) template <class _Tp, class _Container> inline _LIBCPP_INLINE_VISIBILITY -void +typename enable_if< + __is_swappable<_Container>::value, + void +>::type swap(stack<_Tp, _Container>& __x, stack<_Tp, _Container>& __y) _NOEXCEPT_(_NOEXCEPT_(__x.swap(__y))) { diff --git a/libcxx/include/type_traits b/libcxx/include/type_traits index 1ebdafbc69d..99dd679b282 100644 --- a/libcxx/include/type_traits +++ b/libcxx/include/type_traits @@ -105,6 +105,8 @@ namespace std template <class T, class U> struct is_assignable; template <class T> struct is_copy_assignable; template <class T> struct is_move_assignable; + template <class T, class U> struct is_swappable_with; // C++17 + template <class T> struct is_swappable; // C++17 template <class T> struct is_destructible; template <class T, class... Args> struct is_trivially_constructible; @@ -123,6 +125,8 @@ namespace std template <class T, class U> struct is_nothrow_assignable; template <class T> struct is_nothrow_copy_assignable; template <class T> struct is_nothrow_move_assignable; + template <class T, class U> struct is_nothrow_swappable_with; // C++17 + template <class T> struct is_nothrow_swappable; // C++17 template <class T> struct is_nothrow_destructible; template <class T> struct has_virtual_destructor; @@ -300,6 +304,10 @@ namespace std = is_copy_assignable<T>::value; // C++17 template <class T> constexpr bool is_move_assignable_v = is_move_assignable<T>::value; // C++17 + template <class T, class U> constexpr bool is_swappable_with_v + = is_swappable_with<T, U>::value; // C++17 + template <class T> constexpr bool is_swappable_v + = is_swappable<T>::value; // C++17 template <class T> constexpr bool is_destructible_v = is_destructible<T>::value; // C++17 template <class T, class... Args> constexpr bool is_trivially_constructible_v @@ -332,6 +340,10 @@ namespace std = is_nothrow_copy_assignable<T>::value; // C++17 template <class T> constexpr bool is_nothrow_move_assignable_v = is_nothrow_move_assignable<T>::value; // C++17 + template <class T, class U> constexpr bool is_nothrow_swappable_with_v + = is_nothrow_swappable_with<T, U>::value; // C++17 + template <class T> constexpr bool is_nothrow_swappable_v + = is_nothrow_swappable<T>::value; // C++17 template <class T> constexpr bool is_nothrow_destructible_v = is_nothrow_destructible<T>::value; // C++17 template <class T> constexpr bool has_virtual_destructor_v @@ -4421,6 +4433,9 @@ constexpr bool is_nothrow_callable_v = is_nothrow_callable<_Fn, _Ret>::value; #endif // !defined(_LIBCPP_CXX03_LANG) +template <class _Tp> struct __is_swappable; +template <class _Tp> struct __is_nothrow_swappable; + template <class _Tp> inline _LIBCPP_INLINE_VISIBILITY #ifndef _LIBCPP_HAS_NO_ADVANCED_SFINAE @@ -4440,6 +4455,13 @@ swap(_Tp& __x, _Tp& __y) _NOEXCEPT_(is_nothrow_move_constructible<_Tp>::value && __y = _VSTD::move(__t); } +template<class _Tp, size_t _Np> +inline _LIBCPP_INLINE_VISIBILITY +typename enable_if< + __is_swappable<_Tp>::value +>::type +swap(_Tp (&__a)[_Np], _Tp (&__b)[_Np]) _NOEXCEPT_(__is_nothrow_swappable<_Tp>::value); + template <class _ForwardIterator1, class _ForwardIterator2> inline _LIBCPP_INLINE_VISIBILITY void @@ -4455,55 +4477,103 @@ iter_swap(_ForwardIterator1 __a, _ForwardIterator2 __b) namespace __detail { - +// ALL generic swap overloads MUST already have a declaration available at this point. using _VSTD::swap; __nat swap(__any, __any); -template <class _Tp> -struct __swappable +template <class _Tp, class _Up = _Tp, + bool _NotVoid = !is_void<_Tp>::value && !is_void<_Up>::value> +struct __swappable_with { - typedef decltype(swap(_VSTD::declval<_Tp&>(), _VSTD::declval<_Tp&>())) type; - static const bool value = !is_same<type, __nat>::value; + typedef decltype(swap(_VSTD::declval<_Tp>(), _VSTD::declval<_Up>())) __swap1; + typedef decltype(swap(_VSTD::declval<_Up>(), _VSTD::declval<_Tp>())) __swap2; + + static const bool value = !is_same<__swap1, __nat>::value + && !is_same<__swap2, __nat>::value; }; +template <class _Tp, class _Up> +struct __swappable_with<_Tp, _Up, false> : false_type {}; + +template <class _Tp, class _Up = _Tp, bool _Swappable = __swappable_with<_Tp, _Up>::value> +struct __nothrow_swappable_with { + static const bool value = +#ifndef _LIBCPP_HAS_NO_NOEXCEPT + noexcept(swap(_VSTD::declval<_Tp>(), _VSTD::declval<_Up>())) + && noexcept(swap(_VSTD::declval<_Up>(), _VSTD::declval<_Tp>())); +#else + false; +#endif +}; + +template <class _Tp, class _Up> +struct __nothrow_swappable_with<_Tp, _Up, false> : false_type {}; + } // __detail template <class _Tp> struct __is_swappable - : public integral_constant<bool, __detail::__swappable<_Tp>::value> + : public integral_constant<bool, __detail::__swappable_with<_Tp&>::value> { }; -#if __has_feature(cxx_noexcept) || (_GNUC_VER >= 407 && __cplusplus >= 201103L) - -template <bool, class _Tp> -struct __is_nothrow_swappable_imp - : public integral_constant<bool, noexcept(swap(_VSTD::declval<_Tp&>(), - _VSTD::declval<_Tp&>()))> +template <class _Tp> +struct __is_nothrow_swappable + : public integral_constant<bool, __detail::__nothrow_swappable_with<_Tp&>::value> { }; -template <class _Tp> -struct __is_nothrow_swappable_imp<false, _Tp> - : public false_type +#if _LIBCPP_STD_VER > 14 + +template <class _Tp, class _Up> +struct _LIBCPP_TYPE_VIS_ONLY is_swappable_with + : public integral_constant<bool, __detail::__swappable_with<_Tp, _Up>::value> { }; template <class _Tp> -struct __is_nothrow_swappable - : public __is_nothrow_swappable_imp<__is_swappable<_Tp>::value, _Tp> +struct _LIBCPP_TYPE_VIS_ONLY is_swappable + : public conditional< + __is_referenceable<_Tp>::value, + is_swappable_with< + typename add_lvalue_reference<_Tp>::type, + typename add_lvalue_reference<_Tp>::type>, + false_type + >::type { }; -#else // __has_feature(cxx_noexcept) +template <class _Tp, class _Up> +struct _LIBCPP_TYPE_VIS_ONLY is_nothrow_swappable_with + : public integral_constant<bool, __detail::__nothrow_swappable_with<_Tp, _Up>::value> +{ +}; template <class _Tp> -struct __is_nothrow_swappable - : public false_type +struct _LIBCPP_TYPE_VIS_ONLY is_nothrow_swappable + : public conditional< + __is_referenceable<_Tp>::value, + is_nothrow_swappable_with< + typename add_lvalue_reference<_Tp>::type, + typename add_lvalue_reference<_Tp>::type>, + false_type + >::type { }; -#endif // __has_feature(cxx_noexcept) +template <class _Tp, class _Up> +constexpr bool is_swappable_with_v = is_swappable_with<_Tp, _Up>::value; + +template <class _Tp> +constexpr bool is_swappable_v = is_swappable<_Tp>::value; + +template <class _Tp, class _Up> +constexpr bool is_nothrow_swappable_with_v = is_nothrow_swappable_with<_Tp, _Up>::value; + +template <class _Tp> +constexpr bool is_nothrow_swappable_v = is_nothrow_swappable<_Tp>::value; + +#endif // _LIBCPP_STD_VER > 14 #ifdef _LIBCPP_UNDERLYING_TYPE diff --git a/libcxx/include/utility b/libcxx/include/utility index e9db2383a04..27b81a0305e 100644 --- a/libcxx/include/utility +++ b/libcxx/include/utility @@ -82,8 +82,8 @@ struct pair is_nothrow_move_assignable<T2>::value); template <class U, class V> pair& operator=(pair<U, V>&& p); - void swap(pair& p) noexcept(noexcept(swap(first, p.first)) && - noexcept(swap(second, p.second))); + void swap(pair& p) noexcept(is_nothrow_swappable_v<T1> && + is_nothrow_swappable_v<T2>); }; template <class T1, class T2> bool operator==(const pair<T1,T2>&, const pair<T1,T2>&); // constexpr in C++14 @@ -225,10 +225,6 @@ operator>=(const _Tp& __x, const _Tp& __y) // swap_ranges -// forward -template<class _Tp, size_t _Np> -inline _LIBCPP_INLINE_VISIBILITY -void swap(_Tp (&__a)[_Np], _Tp (&__b)[_Np]) _NOEXCEPT_(__is_nothrow_swappable<_Tp>::value); template <class _ForwardIterator1, class _ForwardIterator2> inline _LIBCPP_INLINE_VISIBILITY @@ -240,9 +236,12 @@ swap_ranges(_ForwardIterator1 __first1, _ForwardIterator1 __last1, _ForwardItera return __first2; } +// forward declared in <type_traits> template<class _Tp, size_t _Np> inline _LIBCPP_INLINE_VISIBILITY -void +typename enable_if< + __is_swappable<_Tp>::value +>::type swap(_Tp (&__a)[_Np], _Tp (&__b)[_Np]) _NOEXCEPT_(__is_nothrow_swappable<_Tp>::value) { _VSTD::swap_ranges(__a, __a + _Np, __b); |