Add is_swappable/is_nothrow_swappable traits

git-svn-id: https://llvm.org/svn/llvm-project/libcxx/trunk@267079 91177308-0d34-0410-b5e6-96231b3b80d8
diff --git a/include/array b/include/array
index f0350ea..719286d 100644
--- a/include/array
+++ b/include/array
@@ -34,7 +34,7 @@
 
     // 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 @@
     _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 @@
 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);
 }