This patch partially solves the problem described in N4426, which is basically LWG issue 2456, which in turn is caused by CWG DR 1330. Some remarks: - the __is_swappable and __is_nothrow_swappable are at this time not meant to be general traits, they make the shortcut of automatically transforming their template parameter into a reference, which the truly general trait as described in N4426 wouldn't do. - swap is now constrained.. - ..which means that everything from bits/move.h moves to type_traits since swap now needs type_traits. type_traits becomes ok to include in pre-c++14 modes, but only enables the parts that work in pre-c++14 modes. - this patch does _not_ yet implement N4426.
Tested on Linux-x64. 2015-05-01 Ville Voutilainen <ville.voutilai...@gmail.com> Add __is_nothrow_swappable and take it into use. * libstdc++-v3/include/bits/algorithmfwd.h: Add constraints to the forward-declaration of swap. * include/bits/move.h: Move everything in it to.. * include/type_traits: ..here. * include/type_traits (__swappable_impl::__swappable, __is_nothrow_swappable_impl, __is_nothrow_swappable): New. * include/bits/stl_pair.h (swap): Use __is_nothrow_swappable for the free swap function for pair. * include/bits/stl_queue.h (swap): Use __is_nothrow_swappable for the free swap functions for queue and priority_queue. * include/bits/stl_stack.h (swap): Use __is_nothrow_swappable for the free swap function for stack. * include/debug/array (swap): Use __is_nothrow_swappable for the free swap function for array. * include/profile/array (swap): Likewise. * include/std/array (swap): Likewise. * include/std/tuple (_M_swap): Use __is_nothrow_swappable. * testsuite/20_util/forward/c_neg.cc: Adjust. * testsuite/20_util/forward/f_neg.cc: Likewise. * testsuite/20_util/headers/type_traits/std_c++0x_neg.cc: Remove. * testsuite/20_util/is_nothrow_swappable/requirements/explicit_instantiation.cc: New. * testsuite/20_util/is_nothrow_swappable/requirements/typedefs.cc: Likewise. * testsuite/20_util/is_nothrow_swappable/value.cc: Likewise.
diff --git a/libstdc++-v3/include/bits/algorithmfwd.h b/libstdc++-v3/include/bits/algorithmfwd.h index 1dfc4ad..0e37307 100644 --- a/libstdc++-v3/include/bits/algorithmfwd.h +++ b/libstdc++-v3/include/bits/algorithmfwd.h @@ -567,7 +567,12 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION stable_partition(_BIter, _BIter, _Predicate); template<typename _Tp> - void +#if __cplusplus >= 201103L + typename enable_if<__and_<is_move_constructible<_Tp>, + is_move_assignable<_Tp>>::value>::type +#else + void +#endif swap(_Tp&, _Tp&) #if __cplusplus >= 201103L noexcept(__and_<is_nothrow_move_constructible<_Tp>, @@ -576,7 +581,12 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION ; template<typename _Tp, size_t _Nm> +#if __cplusplus >= 201103L + typename enable_if<__and_<is_move_constructible<_Tp>, + is_move_assignable<_Tp>>::value>::type +#else void +#endif swap(_Tp (&__a)[_Nm], _Tp (&__b)[_Nm]) #if __cplusplus >= 201103L noexcept(noexcept(swap(*__a, *__b))) diff --git a/libstdc++-v3/include/bits/move.h b/libstdc++-v3/include/bits/move.h index 1dfd667..96e2e51 100644 --- a/libstdc++-v3/include/bits/move.h +++ b/libstdc++-v3/include/bits/move.h @@ -30,179 +30,7 @@ #ifndef _MOVE_H #define _MOVE_H 1 -#include <bits/c++config.h> -#include <bits/concept_check.h> - -namespace std _GLIBCXX_VISIBILITY(default) -{ -_GLIBCXX_BEGIN_NAMESPACE_VERSION - - // Used, in C++03 mode too, by allocators, etc. - /** - * @brief Same as C++11 std::addressof - * @ingroup utilities - */ - template<typename _Tp> - inline _Tp* - __addressof(_Tp& __r) _GLIBCXX_NOEXCEPT - { - return reinterpret_cast<_Tp*> - (&const_cast<char&>(reinterpret_cast<const volatile char&>(__r))); - } - -_GLIBCXX_END_NAMESPACE_VERSION -} // namespace - -#if __cplusplus >= 201103L #include <type_traits> // Brings in std::declval too. -namespace std _GLIBCXX_VISIBILITY(default) -{ -_GLIBCXX_BEGIN_NAMESPACE_VERSION - - /** - * @addtogroup utilities - * @{ - */ - - /** - * @brief Forward an lvalue. - * @return The parameter cast to the specified type. - * - * This function is used to implement "perfect forwarding". - */ - template<typename _Tp> - constexpr _Tp&& - forward(typename std::remove_reference<_Tp>::type& __t) noexcept - { return static_cast<_Tp&&>(__t); } - - /** - * @brief Forward an rvalue. - * @return The parameter cast to the specified type. - * - * This function is used to implement "perfect forwarding". - */ - template<typename _Tp> - constexpr _Tp&& - forward(typename std::remove_reference<_Tp>::type&& __t) noexcept - { - static_assert(!std::is_lvalue_reference<_Tp>::value, "template argument" - " substituting _Tp is an lvalue reference type"); - return static_cast<_Tp&&>(__t); - } - - /** - * @brief Convert a value to an rvalue. - * @param __t A thing of arbitrary type. - * @return The parameter cast to an rvalue-reference to allow moving it. - */ - template<typename _Tp> - constexpr typename std::remove_reference<_Tp>::type&& - move(_Tp&& __t) noexcept - { return static_cast<typename std::remove_reference<_Tp>::type&&>(__t); } - - - template<typename _Tp> - struct __move_if_noexcept_cond - : public __and_<__not_<is_nothrow_move_constructible<_Tp>>, - is_copy_constructible<_Tp>>::type { }; - - /** - * @brief Conditionally convert a value to an rvalue. - * @param __x A thing of arbitrary type. - * @return The parameter, possibly cast to an rvalue-reference. - * - * Same as std::move unless the type's move constructor could throw and the - * type is copyable, in which case an lvalue-reference is returned instead. - */ - template<typename _Tp> - constexpr typename - conditional<__move_if_noexcept_cond<_Tp>::value, const _Tp&, _Tp&&>::type - move_if_noexcept(_Tp& __x) noexcept - { return std::move(__x); } - - // declval, from type_traits. - - /** - * @brief Returns the actual address of the object or function - * referenced by r, even in the presence of an overloaded - * operator&. - * @param __r Reference to an object or function. - * @return The actual address. - */ - template<typename _Tp> - inline _Tp* - addressof(_Tp& __r) noexcept - { return std::__addressof(__r); } - - // C++11 version of std::exchange for internal use. - template <typename _Tp, typename _Up = _Tp> - inline _Tp - __exchange(_Tp& __obj, _Up&& __new_val) - { - _Tp __old_val = std::move(__obj); - __obj = std::forward<_Up>(__new_val); - return __old_val; - } - - /// @} group utilities -_GLIBCXX_END_NAMESPACE_VERSION -} // namespace - -#define _GLIBCXX_MOVE(__val) std::move(__val) -#define _GLIBCXX_FORWARD(_Tp, __val) std::forward<_Tp>(__val) -#else -#define _GLIBCXX_MOVE(__val) (__val) -#define _GLIBCXX_FORWARD(_Tp, __val) (__val) -#endif - -namespace std _GLIBCXX_VISIBILITY(default) -{ -_GLIBCXX_BEGIN_NAMESPACE_VERSION - - /** - * @addtogroup utilities - * @{ - */ - - /** - * @brief Swaps two values. - * @param __a A thing of arbitrary type. - * @param __b Another thing of arbitrary type. - * @return Nothing. - */ - template<typename _Tp> - inline void - swap(_Tp& __a, _Tp& __b) -#if __cplusplus >= 201103L - noexcept(__and_<is_nothrow_move_constructible<_Tp>, - is_nothrow_move_assignable<_Tp>>::value) -#endif - { - // concept requirements - __glibcxx_function_requires(_SGIAssignableConcept<_Tp>) - - _Tp __tmp = _GLIBCXX_MOVE(__a); - __a = _GLIBCXX_MOVE(__b); - __b = _GLIBCXX_MOVE(__tmp); - } - - // _GLIBCXX_RESOLVE_LIB_DEFECTS - // DR 809. std::swap should be overloaded for array types. - /// Swap the contents of two arrays. - template<typename _Tp, size_t _Nm> - inline void - swap(_Tp (&__a)[_Nm], _Tp (&__b)[_Nm]) -#if __cplusplus >= 201103L - noexcept(noexcept(swap(*__a, *__b))) -#endif - { - for (size_t __n = 0; __n < _Nm; ++__n) - swap(__a[__n], __b[__n]); - } - - /// @} group utilities -_GLIBCXX_END_NAMESPACE_VERSION -} // namespace #endif /* _MOVE_H */ diff --git a/libstdc++-v3/include/bits/stl_pair.h b/libstdc++-v3/include/bits/stl_pair.h index 3daeb60..490b005 100644 --- a/libstdc++-v3/include/bits/stl_pair.h +++ b/libstdc++-v3/include/bits/stl_pair.h @@ -192,8 +192,8 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION void swap(pair& __p) - noexcept(noexcept(swap(first, __p.first)) - && noexcept(swap(second, __p.second))) + noexcept(__is_nothrow_swappable<_T1>::value + && __is_nothrow_swappable<_T2>::value) { using std::swap; swap(first, __p.first); diff --git a/libstdc++-v3/include/bits/stl_queue.h b/libstdc++-v3/include/bits/stl_queue.h index 48e1ee7..5f8e6fb 100644 --- a/libstdc++-v3/include/bits/stl_queue.h +++ b/libstdc++-v3/include/bits/stl_queue.h @@ -247,7 +247,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION #if __cplusplus >= 201103L void swap(queue& __q) - noexcept(noexcept(swap(c, __q.c))) + noexcept(__is_nothrow_swappable<_Tp>::value) { using std::swap; swap(c, __q.c); @@ -541,7 +541,8 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION #if __cplusplus >= 201103L void swap(priority_queue& __pq) - noexcept(noexcept(swap(c, __pq.c)) && noexcept(swap(comp, __pq.comp))) + noexcept(__is_nothrow_swappable<_Tp>::value + && __is_nothrow_swappable<_Compare>::value) { using std::swap; swap(c, __pq.c); diff --git a/libstdc++-v3/include/bits/stl_stack.h b/libstdc++-v3/include/bits/stl_stack.h index 3ff307f..0ed212e 100644 --- a/libstdc++-v3/include/bits/stl_stack.h +++ b/libstdc++-v3/include/bits/stl_stack.h @@ -221,7 +221,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION #if __cplusplus >= 201103L void swap(stack& __s) - noexcept(noexcept(swap(c, __s.c))) + noexcept(__is_nothrow_swappable<_Tp>::value) { using std::swap; swap(c, __s.c); diff --git a/libstdc++-v3/include/debug/array b/libstdc++-v3/include/debug/array index 31d146e..9bd1f3b 100644 --- a/libstdc++-v3/include/debug/array +++ b/libstdc++-v3/include/debug/array @@ -83,7 +83,7 @@ namespace __debug void swap(array& __other) - noexcept(noexcept(swap(std::declval<_Tp&>(), std::declval<_Tp&>()))) + noexcept(__is_nothrow_swappable<_Tp>::value) { std::swap_ranges(begin(), end(), __other.begin()); } // Iterators. diff --git a/libstdc++-v3/include/profile/array b/libstdc++-v3/include/profile/array index a90e396..4c406d2 100644 --- a/libstdc++-v3/include/profile/array +++ b/libstdc++-v3/include/profile/array @@ -63,7 +63,7 @@ namespace __profile void swap(array& __other) - noexcept(noexcept(swap(std::declval<_Tp&>(), std::declval<_Tp&>()))) + noexcept(__is_nothrow_swappable<_Tp>::value) { std::swap_ranges(begin(), end(), __other.begin()); } // Iterators. diff --git a/libstdc++-v3/include/std/array b/libstdc++-v3/include/std/array index 429506b..72d4649 100644 --- a/libstdc++-v3/include/std/array +++ b/libstdc++-v3/include/std/array @@ -105,7 +105,7 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER void swap(array& __other) - noexcept(noexcept(swap(std::declval<_Tp&>(), std::declval<_Tp&>()))) + noexcept(__is_nothrow_swappable<_Tp>::value) { std::swap_ranges(begin(), end(), __other.begin()); } // Iterators. diff --git a/libstdc++-v3/include/std/tuple b/libstdc++-v3/include/std/tuple index e500a76..5cd6d03 100644 --- a/libstdc++-v3/include/std/tuple +++ b/libstdc++-v3/include/std/tuple @@ -324,9 +324,8 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION protected: void _M_swap(_Tuple_impl& __in) - noexcept(noexcept(swap(std::declval<_Head&>(), - std::declval<_Head&>())) - && noexcept(_M_tail(__in)._M_swap(_M_tail(__in)))) + noexcept(__is_nothrow_swappable<_Head>::value + && noexcept(_M_tail(__in)._M_swap(_M_tail(__in)))) { using std::swap; swap(_M_head(*this), _M_head(__in)); @@ -451,7 +450,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION protected: void _M_swap(_Tuple_impl& __in) - noexcept(noexcept(swap(std::declval<_Head&>(), std::declval<_Head&>()))) + noexcept(__is_nothrow_swappable<_Head>::value) { using std::swap; swap(_M_head(*this), _M_head(__in)); diff --git a/libstdc++-v3/include/std/type_traits b/libstdc++-v3/include/std/type_traits index 03e198a..ea35bc1 100644 --- a/libstdc++-v3/include/std/type_traits +++ b/libstdc++-v3/include/std/type_traits @@ -31,12 +31,12 @@ #pragma GCC system_header +#include <bits/c++config.h> +#include <bits/concept_check.h> + #if __cplusplus < 201103L -# include <bits/c++0x_warning.h> #else -#include <bits/c++config.h> - #ifdef _GLIBCXX_USE_C99_STDINT_TR1 # if defined (__UINT_LEAST16_TYPE__) && defined(__UINT_LEAST32_TYPE__) namespace std @@ -2427,4 +2427,221 @@ _GLIBCXX_END_NAMESPACE_VERSION #endif // C++11 +namespace std _GLIBCXX_VISIBILITY(default) +{ +_GLIBCXX_BEGIN_NAMESPACE_VERSION + + // Used, in C++03 mode too, by allocators, etc. + /** + * @brief Same as C++11 std::addressof + * @ingroup utilities + */ + template<typename _Tp> + inline _Tp* + __addressof(_Tp& __r) _GLIBCXX_NOEXCEPT + { + return reinterpret_cast<_Tp*> + (&const_cast<char&>(reinterpret_cast<const volatile char&>(__r))); + } + +_GLIBCXX_END_NAMESPACE_VERSION +} // namespace + + +#if __cplusplus >= 201103L +namespace std _GLIBCXX_VISIBILITY(default) +{ +_GLIBCXX_BEGIN_NAMESPACE_VERSION + + /** + * @addtogroup utilities + * @{ + */ + + /** + * @brief Forward an lvalue. + * @return The parameter cast to the specified type. + * + * This function is used to implement "perfect forwarding". + */ + template<typename _Tp> + constexpr _Tp&& + forward(typename std::remove_reference<_Tp>::type& __t) noexcept + { return static_cast<_Tp&&>(__t); } + + /** + * @brief Forward an rvalue. + * @return The parameter cast to the specified type. + * + * This function is used to implement "perfect forwarding". + */ + template<typename _Tp> + constexpr _Tp&& + forward(typename std::remove_reference<_Tp>::type&& __t) noexcept + { + static_assert(!std::is_lvalue_reference<_Tp>::value, "template argument" + " substituting _Tp is an lvalue reference type"); + return static_cast<_Tp&&>(__t); + } + + /** + * @brief Convert a value to an rvalue. + * @param __t A thing of arbitrary type. + * @return The parameter cast to an rvalue-reference to allow moving it. + */ + template<typename _Tp> + constexpr typename std::remove_reference<_Tp>::type&& + move(_Tp&& __t) noexcept + { return static_cast<typename std::remove_reference<_Tp>::type&&>(__t); } + + + template<typename _Tp> + struct __move_if_noexcept_cond + : public __and_<__not_<is_nothrow_move_constructible<_Tp>>, + is_copy_constructible<_Tp>>::type { }; + + /** + * @brief Conditionally convert a value to an rvalue. + * @param __x A thing of arbitrary type. + * @return The parameter, possibly cast to an rvalue-reference. + * + * Same as std::move unless the type's move constructor could throw and the + * type is copyable, in which case an lvalue-reference is returned instead. + */ + template<typename _Tp> + constexpr typename + conditional<__move_if_noexcept_cond<_Tp>::value, const _Tp&, _Tp&&>::type + move_if_noexcept(_Tp& __x) noexcept + { return std::move(__x); } + + // declval, from type_traits. + + /** + * @brief Returns the actual address of the object or function + * referenced by r, even in the presence of an overloaded + * operator&. + * @param __r Reference to an object or function. + * @return The actual address. + */ + template<typename _Tp> + inline _Tp* + addressof(_Tp& __r) noexcept + { return std::__addressof(__r); } + + // C++11 version of std::exchange for internal use. + template <typename _Tp, typename _Up = _Tp> + inline _Tp + __exchange(_Tp& __obj, _Up&& __new_val) + { + _Tp __old_val = std::move(__obj); + __obj = std::forward<_Up>(__new_val); + return __old_val; + } + + /// @} group utilities +_GLIBCXX_END_NAMESPACE_VERSION +} // namespace + +#define _GLIBCXX_MOVE(__val) std::move(__val) +#define _GLIBCXX_FORWARD(_Tp, __val) std::forward<_Tp>(__val) +#else +#define _GLIBCXX_MOVE(__val) (__val) +#define _GLIBCXX_FORWARD(_Tp, __val) (__val) +#endif + +namespace std _GLIBCXX_VISIBILITY(default) +{ +_GLIBCXX_BEGIN_NAMESPACE_VERSION + + /** + * @addtogroup utilities + * @{ + */ + + /** + * @brief Swaps two values. + * @param __a A thing of arbitrary type. + * @param __b Another thing of arbitrary type. + * @return Nothing. + */ + template<typename _Tp> + inline +#if __cplusplus >= 201103L + typename enable_if<__and_<is_move_constructible<_Tp>, + is_move_assignable<_Tp>>::value>::type +#else + void +#endif + swap(_Tp& __a, _Tp& __b) +#if __cplusplus >= 201103L + noexcept(__and_<is_nothrow_move_constructible<_Tp>, + is_nothrow_move_assignable<_Tp>>::value) +#endif + { + // concept requirements + __glibcxx_function_requires(_SGIAssignableConcept<_Tp>) + + _Tp __tmp = _GLIBCXX_MOVE(__a); + __a = _GLIBCXX_MOVE(__b); + __b = _GLIBCXX_MOVE(__tmp); + } + +#if __cplusplus >= 201103L + namespace __is_swappable_impl { + template <typename _Tp, typename=void> + struct __is_swappable : public false_type + { }; + } +#endif + + // _GLIBCXX_RESOLVE_LIB_DEFECTS + // DR 809. std::swap should be overloaded for array types. + /// Swap the contents of two arrays. + template<typename _Tp, size_t _Nm> + inline +#if __cplusplus >= 201103L + typename enable_if<__is_swappable_impl::__is_swappable<_Tp>::value>::type +#else + void +#endif + swap(_Tp (&__a)[_Nm], _Tp (&__b)[_Nm]) +#if __cplusplus >= 201103L + noexcept(noexcept(swap(*__a, *__b))) +#endif + { + for (size_t __n = 0; __n < _Nm; ++__n) + swap(__a[__n], __b[__n]); + } + +#if __cplusplus >= 201103L + namespace __is_swappable_impl { + using std::swap; + + template <typename _Tp> + struct __is_swappable<_Tp, __void_t<decltype(swap(declval<_Tp&>(), + declval<_Tp&>()))>> + : public true_type + { }; + } + + template <bool, typename _Tp> + struct __is_nothrow_swappable_impl + : public __bool_constant<noexcept(swap(declval<_Tp&>(), declval<_Tp&>()))> + { }; + + template <typename _Tp> + struct __is_nothrow_swappable_impl<false, _Tp> : public false_type + { }; + + template <typename _Tp> + struct __is_nothrow_swappable + : public __is_nothrow_swappable_impl< + __is_swappable_impl::__is_swappable<_Tp>::value, _Tp> + { }; +#endif + + /// @} group utilities +_GLIBCXX_END_NAMESPACE_VERSION +} // namespace + #endif // _GLIBCXX_TYPE_TRAITS diff --git a/libstdc++-v3/testsuite/20_util/forward/c_neg.cc b/libstdc++-v3/testsuite/20_util/forward/c_neg.cc index ca1c9c5..235338a 100644 --- a/libstdc++-v3/testsuite/20_util/forward/c_neg.cc +++ b/libstdc++-v3/testsuite/20_util/forward/c_neg.cc @@ -18,7 +18,7 @@ // with this library; see the file COPYING3. If not see // <http://www.gnu.org/licenses/>. -// { dg-error "static assertion failed" "" { target *-*-* } 89 } +// { dg-error "static assertion failed" "" { target *-*-* } 2482 } #include <list> diff --git a/libstdc++-v3/testsuite/20_util/forward/f_neg.cc b/libstdc++-v3/testsuite/20_util/forward/f_neg.cc index 971168a..eada1b3 100644 --- a/libstdc++-v3/testsuite/20_util/forward/f_neg.cc +++ b/libstdc++-v3/testsuite/20_util/forward/f_neg.cc @@ -18,7 +18,7 @@ // with this library; see the file COPYING3. If not see // <http://www.gnu.org/licenses/>. -// { dg-error "static assertion failed" "" { target *-*-* } 89 } +// { dg-error "static assertion failed" "" { target *-*-* } 2482 } #include <utility> diff --git a/libstdc++-v3/testsuite/20_util/headers/type_traits/std_c++0x_neg.cc b/libstdc++-v3/testsuite/20_util/headers/type_traits/std_c++0x_neg.cc deleted file mode 100644 index 8452b75..0000000 --- a/libstdc++-v3/testsuite/20_util/headers/type_traits/std_c++0x_neg.cc +++ /dev/null @@ -1,26 +0,0 @@ -// { dg-do compile } -// { dg-options "-std=gnu++98" } - -// Copyright (C) 2007-2015 Free Software Foundation, Inc. -// -// This file is part of the GNU ISO C++ Library. This library is free -// software; you can redistribute it and/or modify it under the -// terms of the GNU General Public License as published by the -// Free Software Foundation; either version 3, or (at your option) -// any later version. - -// This library is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License for more details. - -// You should have received a copy of the GNU General Public License along -// with this library; see the file COPYING3. If not see -// <http://www.gnu.org/licenses/>. - -#include <type_traits> - -// { dg-error "ISO C.. 2011" "" { target *-*-* } 32 } - - - diff --git a/libstdc++-v3/testsuite/20_util/is_nothrow_swappable/requirements/explicit_instantiation.cc b/libstdc++-v3/testsuite/20_util/is_nothrow_swappable/requirements/explicit_instantiation.cc new file mode 100644 index 0000000..93fa94b --- /dev/null +++ b/libstdc++-v3/testsuite/20_util/is_nothrow_swappable/requirements/explicit_instantiation.cc @@ -0,0 +1,27 @@ +// { dg-options "-std=gnu++11" } +// { dg-do compile } + +// Copyright (C) 2015 Free Software Foundation, Inc. +// +// This file is part of the GNU ISO C++ Library. This library is free +// software; you can redistribute it and/or modify it under the +// terms of the GNU General Public License as published by the +// Free Software Foundation; either version 3, or (at your option) +// any later version. + +// This library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// You should have received a copy of the GNU General Public License along +// with this library; see the file COPYING3. If not see +// <http://www.gnu.org/licenses/>. + +#include <type_traits> + +namespace std +{ + typedef short test_type; + template struct std::__is_nothrow_swappable<test_type>; +} diff --git a/libstdc++-v3/testsuite/20_util/is_nothrow_swappable/requirements/typedefs.cc b/libstdc++-v3/testsuite/20_util/is_nothrow_swappable/requirements/typedefs.cc new file mode 100644 index 0000000..2372349 --- /dev/null +++ b/libstdc++-v3/testsuite/20_util/is_nothrow_swappable/requirements/typedefs.cc @@ -0,0 +1,32 @@ +// { dg-options "-std=gnu++11" } +// { dg-do compile } + +// Copyright (C) 2015 Free Software Foundation, Inc. +// +// This file is part of the GNU ISO C++ Library. This library is free +// software; you can redistribute it and/or modify it under the +// terms of the GNU General Public License as published by the +// Free Software Foundation; either version 3, or (at your option) +// any later version. +// +// This library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License along +// with this library; see the file COPYING3. If not see +// <http://www.gnu.org/licenses/>. + +#include <type_traits> + + +void test01() +{ + // Check for required typedefs + typedef std::__is_nothrow_swappable<int> test_type; + typedef test_type::value_type value_type; + typedef test_type::type type; + typedef test_type::type::value_type type_value_type; + typedef test_type::type::type type_type; +} diff --git a/libstdc++-v3/testsuite/20_util/is_nothrow_swappable/value.cc b/libstdc++-v3/testsuite/20_util/is_nothrow_swappable/value.cc new file mode 100644 index 0000000..bc778b5 --- /dev/null +++ b/libstdc++-v3/testsuite/20_util/is_nothrow_swappable/value.cc @@ -0,0 +1,72 @@ +// { dg-options "-std=gnu++11" } +// { dg-do compile } + +// Copyright (C) 2015 Free Software Foundation, Inc. +// +// This file is part of the GNU ISO C++ Library. This library is free +// software; you can redistribute it and/or modify it under the +// terms of the GNU General Public License as published by the +// Free Software Foundation; either version 3, or (at your option) +// any later version. +// +// This library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License along +// with this library; see the file COPYING3. If not see +// <http://www.gnu.org/licenses/>. + +#include <type_traits> +#include <testsuite_tr1.h> +#include <utility> +#include <array> +#include <tuple> +#include <queue> +#include <stack> + +namespace funny { + struct F {}; + void swap(F&, F&) = delete; +} +void test01() +{ + using std::__is_nothrow_swappable; + using std::__is_swappable_impl::__is_swappable; + using namespace __gnu_test; + // Positive tests. + static_assert(test_property<__is_swappable, int>(true), ""); + static_assert(test_property<__is_nothrow_swappable, int>(true), ""); + static_assert(test_property<__is_nothrow_swappable, int[1]>(true), ""); + static_assert(test_property<__is_nothrow_swappable, + std::pair<int, int>>(true), ""); + static_assert(test_property<__is_nothrow_swappable, + std::tuple<int>>(true), ""); + static_assert(test_property<__is_nothrow_swappable, + std::array<int, 1>>(true), ""); + static_assert(test_property<__is_nothrow_swappable, + std::queue<int>>(true), ""); + static_assert(test_property<__is_nothrow_swappable, + std::priority_queue<int>>(true), ""); + static_assert(test_property<__is_nothrow_swappable, + std::stack<int>>(true), ""); + // Negative tests. + static_assert(test_property<__is_swappable, construct::DelCopy>(false), ""); + static_assert(test_property<__is_swappable, funny::F>(false), ""); + static_assert(test_property<__is_swappable, funny::F[1]>(false), ""); + static_assert(test_property<__is_nothrow_swappable, + ThrowCopyConsClass>(false), ""); + static_assert(test_property<__is_nothrow_swappable, + std::pair<ThrowCopyConsClass, ThrowCopyConsClass>>(false), ""); + static_assert(test_property<__is_nothrow_swappable, + std::tuple<ThrowCopyConsClass>>(false), ""); + static_assert(test_property<__is_nothrow_swappable, + std::array<ThrowCopyConsClass, 1>>(false), ""); + static_assert(test_property<__is_nothrow_swappable, + std::queue<ThrowCopyConsClass>>(false), ""); + static_assert(test_property<__is_nothrow_swappable, + std::priority_queue<ThrowCopyConsClass>>(false), ""); + static_assert(test_property<__is_nothrow_swappable, + std::stack<ThrowCopyConsClass>>(false), ""); +}