[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