[cfe-commits] [libcxx] r132204 - in /libcxx/trunk/include: __tuple tuple type_traits utility

Howard Hinnant hhinnant at apple.com
Fri May 27 12:08:18 PDT 2011


Author: hhinnant
Date: Fri May 27 14:08:18 2011
New Revision: 132204

URL: http://llvm.org/viewvc/llvm-project?rev=132204&view=rev
Log:
noexcept for <tuple>.  And in the process learned that I had done it wrong for pair's swap.  I needed to create an __is_nothrow_swappable<T>::value trait that was smart enought to answer false when __is_swappable<T>::value is false.  Otherwise one gets compile-time errors when using pair or tuple of non-swappable types, even if you never try to swap the pair or tuple.

Modified:
    libcxx/trunk/include/__tuple
    libcxx/trunk/include/tuple
    libcxx/trunk/include/type_traits
    libcxx/trunk/include/utility

Modified: libcxx/trunk/include/__tuple
URL: http://llvm.org/viewvc/llvm-project/libcxx/trunk/include/__tuple?rev=132204&r1=132203&r2=132204&view=diff
==============================================================================
--- libcxx/trunk/include/__tuple (original)
+++ libcxx/trunk/include/__tuple Fri May 27 14:08:18 2011
@@ -78,27 +78,27 @@
 
 template <size_t _Ip, class ..._Tp>
 typename tuple_element<_Ip, tuple<_Tp...> >::type&
-get(tuple<_Tp...>&);
+get(tuple<_Tp...>&) _NOEXCEPT;
 
 template <size_t _Ip, class ..._Tp>
 const typename tuple_element<_Ip, tuple<_Tp...> >::type&
-get(const tuple<_Tp...>&);
+get(const tuple<_Tp...>&) _NOEXCEPT;
 
 template <size_t _Ip, class ..._Tp>
 typename tuple_element<_Ip, tuple<_Tp...> >::type&&
-get(tuple<_Tp...>&&);
+get(tuple<_Tp...>&&) _NOEXCEPT;
 
 template <size_t _Ip, class _T1, class _T2>
 typename tuple_element<_Ip, pair<_T1, _T2> >::type&
-get(pair<_T1, _T2>&);
+get(pair<_T1, _T2>&) _NOEXCEPT;
 
 template <size_t _Ip, class _T1, class _T2>
 const typename tuple_element<_Ip, pair<_T1, _T2> >::type&
-get(const pair<_T1, _T2>&);
+get(const pair<_T1, _T2>&) _NOEXCEPT;
 
 template <size_t _Ip, class _T1, class _T2>
 typename tuple_element<_Ip, pair<_T1, _T2> >::type&&
-get(pair<_T1, _T2>&&);
+get(pair<_T1, _T2>&&) _NOEXCEPT;
 
 template <size_t _Ip, class _Tp, size_t _Size>
 _Tp&

Modified: libcxx/trunk/include/tuple
URL: http://llvm.org/viewvc/llvm-project/libcxx/trunk/include/tuple?rev=132204&r1=132203&r2=132204&view=diff
==============================================================================
--- libcxx/trunk/include/tuple (original)
+++ libcxx/trunk/include/tuple Fri May 27 14:08:18 2011
@@ -25,7 +25,7 @@
     template <class... U>
         explicit tuple(U&&...);
     tuple(const tuple&) = default;
-    tuple(tuple&&);
+    tuple(tuple&&) = default;
     template <class... U>
         tuple(const tuple<U...>&);
     template <class... U>
@@ -56,7 +56,8 @@
         tuple(allocator_arg_t, const Alloc& a, pair<U1, U2>&&);
 
     tuple& operator=(const tuple&);
-    tuple& operator=(tuple&&);
+    tuple&
+        operator=(tuple&&) noexcept(AND(is_nothrow_move_assignable<T>::value ...));
     template <class... U>
         tuple& operator=(const tuple<U...>&);
     template <class... U>
@@ -66,14 +67,14 @@
     template <class U1, class U2>
         tuple& operator=(pair<U1, U2>&&); //iffsizeof...(T) == 2
 
-    void swap(tuple&);
+    void swap(tuple&) noexcept(AND(swap(declval<T&>(), declval<T&>())...));
 };
 
 const unspecified ignore;
 
 template <class... T> tuple<V...>  make_tuple(T&&...);
-template <class... T> tuple<ATypes...> forward_as_tuple(T&&...);
-template <class... T> tuple<T&...> tie(T&...);
+template <class... T> tuple<ATypes...> forward_as_tuple(T&&...) noexcept;
+template <class... T> tuple<T&...> tie(T&...) noexcept;
 template <class... Tuples> tuple<CTypes...> tuple_cat(Tuples&&... tpls);
   
 // 20.4.1.4, tuple helper classes:
@@ -83,9 +84,15 @@
 template <intsize_t I, class... T> class tuple_element<I, tuple<T...>>;
 
 // 20.4.1.5, element access:
-template <intsize_t I, class... T> typename tuple_element<I, tuple<T...>>::type& get(tuple<T...>&);
-template <intsize_t I, class... T> typename tuple_element<I, tuple<T...>>::type const& get(const tuple<T...>&);
-template <intsize_t I, class... T> typename tuple_element<I, tuple<T...>>::type&& get(tuple<T...>&&);
+template <intsize_t I, class... T>
+    typename tuple_element<I, tuple<T...>>::type&
+    get(tuple<T...>&) noexcept;
+template <intsize_t I, class... T>
+    typename tuple_element<I, tuple<T...>>::type const&
+    get(const tuple<T...>&) noexcept;
+template <intsize_t I, class... T>
+    typename tuple_element<I, tuple<T...>>::type&&
+    get(tuple<T...>&&) noexcept;
 
 // 20.4.1.6, relational operators:
 template<class... T, class... U> bool operator==(const tuple<T...>&, const tuple<U...>&);
@@ -99,7 +106,8 @@
   struct uses_allocator<tuple<Types...>, Alloc>;
 
 template <class... Types>
-  void swap(tuple<Types...>& x, tuple<Types...>& y);
+  void
+  swap(tuple<Types...>& x, tuple<Types...>& y) noexcept(noexcept(x.swap(y)));
 
 }  // std
 
@@ -142,6 +150,7 @@
 template <size_t _Ip, class _Hp, bool _Ep>
 inline _LIBCPP_INLINE_VISIBILITY
 void swap(__tuple_leaf<_Ip, _Hp, _Ep>& __x, __tuple_leaf<_Ip, _Hp, _Ep>& __y)
+    _NOEXCEPT_(__is_nothrow_swappable<_Hp>::value)
 {
     swap(__x.get(), __y.get());
 }
@@ -256,7 +265,7 @@
         }
 
     _LIBCPP_INLINE_VISIBILITY
-    int swap(__tuple_leaf& __t)
+    int swap(__tuple_leaf& __t) _NOEXCEPT_(__is_nothrow_swappable<__tuple_leaf>::value)
     {
         _STD::swap(*this, __t);
         return 0;
@@ -324,7 +333,9 @@
             return *this;
         }
 
-    _LIBCPP_INLINE_VISIBILITY int swap(__tuple_leaf& __t)
+    _LIBCPP_INLINE_VISIBILITY
+    int
+    swap(__tuple_leaf& __t) _NOEXCEPT_(__is_nothrow_swappable<__tuple_leaf>::value)
     {
         _STD::swap(*this, __t);
         return 0;
@@ -338,6 +349,20 @@
 _LIBCPP_INLINE_VISIBILITY
 void __swallow(_Tp&&...) {}
 
+template <bool ...> struct __all;
+
+template <>
+struct __all<>
+{
+    static const bool value = true;
+};
+
+template <bool _B0, bool ... _B>
+struct __all<_B0, _B...>
+{
+    static const bool value = _B0 && __all<_B...>::value;
+};
+
 // __tuple_impl
 
 template<class _Indx, class ..._Tp> struct __tuple_impl;
@@ -412,6 +437,7 @@
 
     _LIBCPP_INLINE_VISIBILITY
     void swap(__tuple_impl& __t)
+        _NOEXCEPT_(__all<__is_nothrow_swappable<_Tp>::value...>::value)
     {
         __swallow(__tuple_leaf<_Indx, _Tp>::swap(static_cast<__tuple_leaf<_Indx, _Tp>&>(__t))...);
     }
@@ -533,7 +559,8 @@
         }
 
     _LIBCPP_INLINE_VISIBILITY
-    void swap(tuple& __t) {base_.swap(__t.base_);}
+    void swap(tuple& __t) _NOEXCEPT_(__all<__is_nothrow_swappable<_Tp>::value...>::value)
+        {base_.swap(__t.base_);}
 };
 
 template <>
@@ -555,13 +582,15 @@
     _LIBCPP_INLINE_VISIBILITY
         tuple(allocator_arg_t, const _Alloc&, array<_U, 0>) {}
     _LIBCPP_INLINE_VISIBILITY
-    void swap(tuple&) {}
+    void swap(tuple&) _NOEXCEPT {}
 };
 
 template <class ..._Tp>
 inline _LIBCPP_INLINE_VISIBILITY
 void
-swap(tuple<_Tp...>& __t, tuple<_Tp...>& __u) {__t.swap(__u);}
+swap(tuple<_Tp...>& __t, tuple<_Tp...>& __u)
+                 _NOEXCEPT_(__all<__is_nothrow_swappable<_Tp>::value...>::value)
+    {__t.swap(__u);}
 
 // get
 

Modified: libcxx/trunk/include/type_traits
URL: http://llvm.org/viewvc/llvm-project/libcxx/trunk/include/type_traits?rev=132204&r1=132203&r2=132204&view=diff
==============================================================================
--- libcxx/trunk/include/type_traits (original)
+++ libcxx/trunk/include/type_traits Fri May 27 14:08:18 2011
@@ -3019,6 +3019,54 @@
     swap(*__a, *__b);
 }
 
+// __swappable
+
+__nat swap(__any, __any);
+
+template <class _Tp>
+struct __swappable
+{
+    typedef decltype(swap(_STD::declval<_Tp&>(), _STD::declval<_Tp&>())) type;
+    static const bool value = !is_same<type, __nat>::value;
+};
+
+template <class _Tp>
+struct __is_swappable
+    : public integral_constant<bool, __swappable<_Tp>::value>
+{
+};
+
+#if __has_feature(cxx_noexcept)
+
+template <bool, class _Tp>
+struct __is_nothrow_swappable_imp
+    : public integral_constant<bool, noexcept(swap(_STD::declval<_Tp&>(),
+                                                   _STD::declval<_Tp&>()))>
+{
+};
+
+template <class _Tp>
+struct __is_nothrow_swappable_imp<false, _Tp>
+    : public false_type
+{
+};
+
+template <class _Tp>
+struct __is_nothrow_swappable
+    : public __is_nothrow_swappable_imp<__is_swappable<_Tp>::value, _Tp>
+{
+};
+
+#else  // __has_feature(cxx_noexcept)
+
+template <class _Tp>
+struct __is_nothrow_swappable
+    : public false_type
+{
+};
+
+#endif  // __has_feature(cxx_noexcept)
+
 _LIBCPP_END_NAMESPACE_STD
 
 #endif  // _LIBCPP_TYPE_TRAITS

Modified: libcxx/trunk/include/utility
URL: http://llvm.org/viewvc/llvm-project/libcxx/trunk/include/utility?rev=132204&r1=132203&r2=132204&view=diff
==============================================================================
--- libcxx/trunk/include/utility (original)
+++ libcxx/trunk/include/utility Fri May 27 14:08:18 2011
@@ -181,8 +181,7 @@
 template<class _Tp, size_t _N>
 inline _LIBCPP_INLINE_VISIBILITY
 void
-swap(_Tp (&__a)[_N], _Tp (&__b)[_N])
-      _NOEXCEPT_(_NOEXCEPT_(swap(_STD::declval<_Tp&>(), _STD::declval<_Tp&>())))
+swap(_Tp (&__a)[_N], _Tp (&__b)[_N]) _NOEXCEPT_(__is_nothrow_swappable<_Tp>::value)
 {
     _STD::swap_ranges(__a, __a + _N, __b);
 }
@@ -311,13 +310,8 @@
 #endif  // _LIBCPP_HAS_NO_RVALUE_REFERENCES
     _LIBCPP_INLINE_VISIBILITY
     void
-    swap(pair& __p) _NOEXCEPT_(
-//                    _NOEXCEPT_(_STD::iter_swap(&first, &__p.first)) &&
-//                    _NOEXCEPT_(_STD::iter_swap(&second, &__p.second)))
-                      _NOEXCEPT_(_STD::iter_swap(&_STD::declval<first_type&>(),
-                                                 &_STD::declval<first_type&>())) &&
-                      _NOEXCEPT_(_STD::iter_swap(&_STD::declval<second_type&>(),
-                                                 &_STD::declval<second_type&>())))
+    swap(pair& __p) _NOEXCEPT_(__is_nothrow_swappable<first_type>::value &&
+                               __is_nothrow_swappable<second_type>::value)
     {
         _STD::iter_swap(&first, &__p.first);
         _STD::iter_swap(&second, &__p.second);
@@ -385,8 +379,8 @@
 inline _LIBCPP_INLINE_VISIBILITY
 void
 swap(pair<_T1, _T2>& __x, pair<_T1, _T2>& __y)
-//                                        _NOEXCEPT_(_NOEXCEPT_(__x.swap(__y)))
-    _NOEXCEPT_(_NOEXCEPT_((_STD::declval<pair<_T1, _T2>&>().swap(_STD::declval<pair<_T1, _T2>&>()))))
+                     _NOEXCEPT_((__is_nothrow_swappable<_T1>::value &&
+                                 __is_nothrow_swappable<_T2>::value))
 {
     __x.swap(__y);
 }
@@ -481,13 +475,13 @@
     static
     _LIBCPP_INLINE_VISIBILITY
     _T1&
-    get(pair<_T1, _T2>& __p) {return __p.first;}
+    get(pair<_T1, _T2>& __p) _NOEXCEPT {return __p.first;}
 
     template <class _T1, class _T2>
     static
     _LIBCPP_INLINE_VISIBILITY
     const _T1&
-    get(const pair<_T1, _T2>& __p) {return __p.first;}
+    get(const pair<_T1, _T2>& __p) _NOEXCEPT {return __p.first;}
 
 #ifndef _LIBCPP_HAS_NO_RVALUE_REFERENCES
 
@@ -495,7 +489,7 @@
     static
     _LIBCPP_INLINE_VISIBILITY
     _T1&&
-    get(pair<_T1, _T2>&& __p) {return _STD::forward<_T1>(__p.first);}
+    get(pair<_T1, _T2>&& __p) _NOEXCEPT {return _STD::forward<_T1>(__p.first);}
 
 #endif  // _LIBCPP_HAS_NO_RVALUE_REFERENCES
 };
@@ -507,13 +501,13 @@
     static
     _LIBCPP_INLINE_VISIBILITY
     _T2&
-    get(pair<_T1, _T2>& __p) {return __p.second;}
+    get(pair<_T1, _T2>& __p) _NOEXCEPT {return __p.second;}
 
     template <class _T1, class _T2>
     static
     _LIBCPP_INLINE_VISIBILITY
     const _T2&
-    get(const pair<_T1, _T2>& __p) {return __p.second;}
+    get(const pair<_T1, _T2>& __p) _NOEXCEPT {return __p.second;}
 
 #ifndef _LIBCPP_HAS_NO_RVALUE_REFERENCES
 
@@ -521,7 +515,7 @@
     static
     _LIBCPP_INLINE_VISIBILITY
     _T2&&
-    get(pair<_T1, _T2>&& __p) {return _STD::forward<_T2>(__p.second);}
+    get(pair<_T1, _T2>&& __p) _NOEXCEPT {return _STD::forward<_T2>(__p.second);}
 
 #endif  // _LIBCPP_HAS_NO_RVALUE_REFERENCES
 };
@@ -529,7 +523,7 @@
 template <size_t _Ip, class _T1, class _T2>
 _LIBCPP_INLINE_VISIBILITY inline
 typename tuple_element<_Ip, pair<_T1, _T2> >::type&
-get(pair<_T1, _T2>& __p)
+get(pair<_T1, _T2>& __p) _NOEXCEPT
 {
     return __get_pair<_Ip>::get(__p);
 }
@@ -537,7 +531,7 @@
 template <size_t _Ip, class _T1, class _T2>
 _LIBCPP_INLINE_VISIBILITY inline
 const typename tuple_element<_Ip, pair<_T1, _T2> >::type&
-get(const pair<_T1, _T2>& __p)
+get(const pair<_T1, _T2>& __p) _NOEXCEPT
 {
     return __get_pair<_Ip>::get(__p);
 }
@@ -547,7 +541,7 @@
 template <size_t _Ip, class _T1, class _T2>
 _LIBCPP_INLINE_VISIBILITY inline
 typename tuple_element<_Ip, pair<_T1, _T2> >::type&&
-get(pair<_T1, _T2>&& __p)
+get(pair<_T1, _T2>&& __p) _NOEXCEPT
 {
     return __get_pair<_Ip>::get(_STD::move(__p));
 }





More information about the cfe-commits mailing list