summaryrefslogtreecommitdiffstats
path: root/libcxx/include
diff options
context:
space:
mode:
authorEric Fiselier <eric@efcs.ca>2016-04-21 23:38:59 +0000
committerEric Fiselier <eric@efcs.ca>2016-04-21 23:38:59 +0000
commitf07dd8d0a925dd8cbde7bb6198c1ba92446110ea (patch)
tree581032748ea2b3640d2e7f033f2e651eb67416bd /libcxx/include
parentc89755e4cbad7a46d747f3b2d49c50a80855a801 (diff)
downloadbcm5719-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/algorithm2
-rw-r--r--libcxx/include/array16
-rw-r--r--libcxx/include/map4
-rw-r--r--libcxx/include/memory5
-rw-r--r--libcxx/include/queue16
-rw-r--r--libcxx/include/stack7
-rw-r--r--libcxx/include/type_traits112
-rw-r--r--libcxx/include/utility13
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);
OpenPOWER on IntegriCloud