From 6b9539e2aa811e84847db2deb1adfc288c7157b7 Mon Sep 17 00:00:00 2001 From: Daniel Kruegler Date: Thu, 16 Jun 2016 15:07:19 +0000 Subject: Provide swappable traits (p0185r1) 2016-06-16 Daniel Kruegler Provide swappable traits (p0185r1) * include/std/type_traits (is_swappable, is_nothrow_swappable, is_swappable_with, is_nothrow_swappable_with, is_swappable_v, is_nothrow_swappable_v, is_swappable_with_v, is_nothrow_swappable_with_v): New. * include/bits/stl_pair.h: Use it as per p0185r1. * include/bits/stl_queue.h: Likewise. * include/bits/stl_stack.h: Likewise. * include/bits/unique_ptr.h: Likewise. * include/std/tuple: Likewise. * include/std/array: Likewise. Fix zero-size member swap. * include/bits/hashtable.h: Use __and_. * testsuite/20_util/is_nothrow_swappable/requirements/ explicit_instantiation.cc: Change test options to std=gnu++17. * testsuite/20_util/is_nothrow_swappable/requirements/typedefs.cc: Likewise. * testsuite/20_util/is_nothrow_swappable/value.cc: Likewise. * testsuite/20_util/is_swappable/requirements/ explicit_instantiation.cc: Likewise. * testsuite/20_util/is_swappable/requirements/typedefs.cc: Likewise. * testsuite/20_util/is_swappable/value.cc: Likewise. * testsuite/20_util/is_nothrow_swappable/requirements/ explicit_instantiation_ext.cc: New. * testsuite/20_util/is_nothrow_swappable/requirements/typedefs_ext.cc: New. * testsuite/20_util/is_nothrow_swappable/value.h: New. * testsuite/20_util/is_nothrow_swappable/value_ext.cc: New. * testsuite/20_util/is_nothrow_swappable_with/requirements/ explicit_instantiation.cc: New. * testsuite/20_util/is_nothrow_swappable_with/requirements/typedefs.cc: New. * testsuite/20_util/is_nothrow_swappable_with/value.cc: New. * testsuite/20_util/is_swappable/requirements/ explicit_instantiation_ext.cc: New. * testsuite/20_util/is_swappable/requirements/typedefs_ext.cc: New. * testsuite/20_util/is_swappable/value.h: New. * testsuite/20_util/is_swappable/value_ext.cc: New. * testsuite/20_util/is_swappable_with/requirements/ explicit_instantiation.cc: New. * testsuite/20_util/is_swappable_with/requirements/typedefs.cc: New. * testsuite/20_util/is_swappable_with/value.cc: New. * testsuite/23_containers/array/tuple_interface/get_neg.cc: Adjust dg-error line numbers. * testsuite/23_containers/array/tuple_interface/tuple_element_neg.cc: Likewise. From-SVN: r237531 --- libstdc++-v3/include/std/array | 16 ++++- libstdc++-v3/include/std/tuple | 9 ++- libstdc++-v3/include/std/type_traits | 112 ++++++++++++++++++++++++++++++++++- 3 files changed, 133 insertions(+), 4 deletions(-) (limited to 'libstdc++-v3/include/std') diff --git a/libstdc++-v3/include/std/array b/libstdc++-v3/include/std/array index ee46f68..73d2669 100644 --- a/libstdc++-v3/include/std/array +++ b/libstdc++-v3/include/std/array @@ -48,6 +48,8 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER struct __array_traits { typedef _Tp _Type[_Nm]; + typedef __is_swappable<_Tp> _Is_swappable; + typedef __is_nothrow_swappable<_Tp> _Is_nothrow_swappable; static constexpr _Tp& _S_ref(const _Type& __t, std::size_t __n) noexcept @@ -62,6 +64,8 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER struct __array_traits<_Tp, 0> { struct _Type { }; + typedef true_type _Is_swappable; + typedef true_type _Is_nothrow_swappable; static constexpr _Tp& _S_ref(const _Type&, std::size_t) noexcept @@ -114,7 +118,7 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER void swap(array& __other) - noexcept(__is_nothrow_swappable<_Tp>::value) + noexcept(_AT_Type::_Is_nothrow_swappable::value) { std::swap_ranges(begin(), end(), __other.begin()); } // Iterators. @@ -271,7 +275,15 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER // Specialized algorithms. template - inline void + inline +#if __cplusplus > 201402L || !defined(__STRICT_ANSI__) // c++1z or gnu++11 + // Constrained free swap overload, see p0185r1 + typename enable_if< + _GLIBCXX_STD_C::__array_traits<_Tp, _Nm>::_Is_swappable::value + >::type +#else + void +#endif swap(array<_Tp, _Nm>& __one, array<_Tp, _Nm>& __two) noexcept(noexcept(__one.swap(__two))) { __one.swap(__two); } diff --git a/libstdc++-v3/include/std/tuple b/libstdc++-v3/include/std/tuple index 9c425e7..180a346 100644 --- a/libstdc++-v3/include/std/tuple +++ b/libstdc++-v3/include/std/tuple @@ -1569,7 +1569,14 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION /// swap template - inline void + inline +#if __cplusplus > 201402L || !defined(__STRICT_ANSI__) // c++1z or gnu++11 + // Constrained free swap overload, see p0185r1 + typename enable_if<__and_<__is_swappable<_Elements>...>::value + >::type +#else + void +#endif swap(tuple<_Elements...>& __x, tuple<_Elements...>& __y) noexcept(noexcept(__x.swap(__y))) { __x.swap(__y); } diff --git a/libstdc++-v3/include/std/type_traits b/libstdc++-v3/include/std/type_traits index eac2492..e5c0d46 100644 --- a/libstdc++-v3/include/std/type_traits +++ b/libstdc++-v3/include/std/type_traits @@ -2631,7 +2631,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION static false_type __test(...); }; - } + } // namespace __swappable_details template struct __is_swappable_impl @@ -2657,6 +2657,116 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION : public __is_nothrow_swappable_impl<_Tp>::type { }; +#if __cplusplus > 201402L || !defined(__STRICT_ANSI__) // c++1z or gnu++11 +#define __cpp_lib_is_swappable 201603 + /// Metafunctions used for detecting swappable types: p0185r1 + + /// is_swappable + template + struct is_swappable + : public __is_swappable_impl<_Tp>::type + { }; + + /// is_nothrow_swappable + template + struct is_nothrow_swappable + : public __is_nothrow_swappable_impl<_Tp>::type + { }; + +#if __cplusplus >= 201402L + /// is_swappable_v + template + constexpr bool is_swappable_v = is_swappable<_Tp>::value; + + /// is_nothrow_swappable_v + template + constexpr bool is_nothrow_swappable_v = is_nothrow_swappable<_Tp>::value; +#endif // __cplusplus >= 201402L + + namespace __swappable_with_details { + using std::swap; + + struct __do_is_swappable_with_impl + { + template(), std::declval<_Up>())), + typename + = decltype(swap(std::declval<_Up>(), std::declval<_Tp>()))> + static true_type __test(int); + + template + static false_type __test(...); + }; + + struct __do_is_nothrow_swappable_with_impl + { + template + static __bool_constant< + noexcept(swap(std::declval<_Tp>(), std::declval<_Up>())) + && + noexcept(swap(std::declval<_Up>(), std::declval<_Tp>())) + > __test(int); + + template + static false_type __test(...); + }; + + } // namespace __swappable_with_details + + template + struct __is_swappable_with_impl + : public __swappable_with_details::__do_is_swappable_with_impl + { + typedef decltype(__test<_Tp, _Up>(0)) type; + }; + + // Optimization for the homogenous lvalue case, not required: + template + struct __is_swappable_with_impl<_Tp&, _Tp&> + : public __swappable_details::__do_is_swappable_impl + { + typedef decltype(__test<_Tp&>(0)) type; + }; + + template + struct __is_nothrow_swappable_with_impl + : public __swappable_with_details::__do_is_nothrow_swappable_with_impl + { + typedef decltype(__test<_Tp, _Up>(0)) type; + }; + + // Optimization for the homogenous lvalue case, not required: + template + struct __is_nothrow_swappable_with_impl<_Tp&, _Tp&> + : public __swappable_details::__do_is_nothrow_swappable_impl + { + typedef decltype(__test<_Tp&>(0)) type; + }; + + /// is_swappable_with + template + struct is_swappable_with + : public __is_swappable_with_impl<_Tp, _Up>::type + { }; + + /// is_nothrow_swappable_with + template + struct is_nothrow_swappable_with + : public __is_nothrow_swappable_with_impl<_Tp, _Up>::type + { }; + +#if __cplusplus >= 201402L + /// is_swappable_with_v + template + constexpr bool is_swappable_with_v = is_swappable_with<_Tp, _Up>::value; + + /// is_nothrow_swappable_with_v + template + constexpr bool is_nothrow_swappable_with_v = + is_nothrow_swappable_with<_Tp, _Up>::value; +#endif // __cplusplus >= 201402L +#endif + _GLIBCXX_END_NAMESPACE_VERSION } // namespace std -- cgit v1.1