Extracted C++11 implementation of is_nothrow_swappable to a separate header.

Also modified the implementation to avoid referencing any potential swap
overloads in namespace boost, unless these overloads are found by ADL.

Added tests to verify is_nothrow_swappable works with ADL.
This commit is contained in:
Andrey Semashev committed 2023-02-18 23:53:35 +03:00
1 parent 2370288a79
commit 1c31fee575
3 files changed
+111 -29

No files matched your search

+71 -7
View File
@@ -1,4 +1,3 @@
// Copyright 2017 Peter Dimov
//
// Distributed under the Boost Software License, Version 1.0.
@@ -17,6 +16,13 @@
#include "check_integral_constant.hpp"
#include <utility>
// These conditions should be similar to those in is_nothrow_swappable.hpp
#if defined(BOOST_NO_SFINAE_EXPR) || defined(BOOST_NO_CXX11_NOEXCEPT) || defined(BOOST_NO_CXX11_DECLTYPE) || defined(BOOST_NO_CXX11_FUNCTION_TEMPLATE_DEFAULT_ARGS) \
|| BOOST_WORKAROUND(BOOST_GCC, < 40700) \
|| (defined(__GLIBCXX__) && __GLIBCXX__ <= 20120301) // built-in clang++ -std=c++11 on Travis, w/ libstdc++ 4.6
#define BOOST_TYPE_TRAITS_IS_NOTHROW_SWAPPABLE_EMULATED
#endif
struct X
{
};
@@ -45,6 +51,44 @@ struct U
void swap(U&, U&) {}
#if !defined(BOOST_TYPE_TRAITS_IS_NOTHROW_SWAPPABLE_EMULATED) && !defined(BOOST_NO_CXX11_DELETED_FUNCTIONS)
namespace test_ns {
// Not swappable using std::swap, but swappable using test_ns::swap
struct only_adl_swappable
{
only_adl_swappable(only_adl_swappable const&) = delete;
only_adl_swappable& operator= (only_adl_swappable const&) = delete;
};
inline void swap(only_adl_swappable&, only_adl_swappable&) BOOST_NOEXCEPT {}
} // namespace test_ns
namespace boost {
namespace type_traits_is_nothrow_swappable_test {
// Some type that is defined within boost namespace and that has a specialized swap overload
struct swappable
{
swappable(swappable const&) = delete;
swappable& operator= (swappable const&) = delete;
};
// This overload should be selected by is_nothrow_swappable
inline void swap(swappable&, swappable&) BOOST_NOEXCEPT {}
} // namespace type_traits_is_nothrow_swappable_test
// Some generic swap implementation, such as the one from Boost.Swap. This overload should *not* be selected by is_nothrow_swappable.
template< typename T1, typename T2 >
inline void swap(T1&, T2&) {}
} // namespace boost
#endif
TT_TEST_BEGIN(is_nothrow_swappable)
BOOST_CHECK_INTEGRAL_CONSTANT(::tt::is_nothrow_swappable<int>::value, true);
@@ -52,9 +96,7 @@ BOOST_CHECK_INTEGRAL_CONSTANT(::tt::is_nothrow_swappable<int const>::value, fals
BOOST_CHECK_INTEGRAL_CONSTANT(::tt::is_nothrow_swappable<int volatile>::value, true);
BOOST_CHECK_INTEGRAL_CONSTANT(::tt::is_nothrow_swappable<int const volatile>::value, false);
#if defined(BOOST_NO_SFINAE_EXPR) || defined(BOOST_NO_CXX11_NOEXCEPT) || defined(BOOST_NO_CXX11_DECLTYPE) || defined(BOOST_NO_CXX11_FUNCTION_TEMPLATE_DEFAULT_ARGS) \
|| BOOST_WORKAROUND(BOOST_GCC, < 40700)\
|| (defined(__GLIBCXX__) && __GLIBCXX__ <= 20120301) // built-in clang++ -std=c++11 on Travis, w/ libstdc++ 4.6
#if defined(BOOST_TYPE_TRAITS_IS_NOTHROW_SWAPPABLE_EMULATED)
BOOST_CHECK_INTEGRAL_CONSTANT(::tt::is_nothrow_swappable<int[2]>::value, false);
BOOST_CHECK_INTEGRAL_CONSTANT(::tt::is_nothrow_swappable<int const[2]>::value, false);
BOOST_CHECK_INTEGRAL_CONSTANT(::tt::is_nothrow_swappable<int volatile[2]>::value, false);
@@ -71,9 +113,7 @@ BOOST_CHECK_INTEGRAL_CONSTANT(::tt::is_nothrow_swappable<void const>::value, fal
BOOST_CHECK_INTEGRAL_CONSTANT(::tt::is_nothrow_swappable<void volatile>::value, false);
BOOST_CHECK_INTEGRAL_CONSTANT(::tt::is_nothrow_swappable<void const volatile>::value, false);
#if defined(BOOST_NO_SFINAE_EXPR) || defined(BOOST_NO_CXX11_NOEXCEPT) || defined(BOOST_NO_CXX11_DECLTYPE) || defined(BOOST_NO_CXX11_FUNCTION_TEMPLATE_DEFAULT_ARGS) \
|| BOOST_WORKAROUND(BOOST_GCC, < 40700)\
|| (defined(__GLIBCXX__) && __GLIBCXX__ <= 20120301) // built-in clang++ -std=c++11 on Travis, w/ libstdc++ 4.6
#if defined(BOOST_TYPE_TRAITS_IS_NOTHROW_SWAPPABLE_EMULATED)
BOOST_CHECK_INTEGRAL_CONSTANT(::tt::is_nothrow_swappable<X>::value, false);
BOOST_CHECK_INTEGRAL_CONSTANT(::tt::is_nothrow_swappable<X const>::value, false);
@@ -157,6 +197,30 @@ BOOST_CHECK_INTEGRAL_CONSTANT((::tt::is_nothrow_swappable<std::pair<V, int> cons
BOOST_CHECK_INTEGRAL_CONSTANT((::tt::is_nothrow_swappable<std::pair<V, int> volatile>::value), false);
BOOST_CHECK_INTEGRAL_CONSTANT((::tt::is_nothrow_swappable<std::pair<V, int> const volatile>::value), false);
#if !defined(BOOST_NO_CXX11_DELETED_FUNCTIONS)
BOOST_CHECK_INTEGRAL_CONSTANT(::tt::is_nothrow_swappable<test_ns::only_adl_swappable>::value, true);
BOOST_CHECK_INTEGRAL_CONSTANT(::tt::is_nothrow_swappable<test_ns::only_adl_swappable const>::value, false);
BOOST_CHECK_INTEGRAL_CONSTANT(::tt::is_nothrow_swappable<test_ns::only_adl_swappable volatile>::value, false);
BOOST_CHECK_INTEGRAL_CONSTANT(::tt::is_nothrow_swappable<test_ns::only_adl_swappable const volatile>::value, false);
BOOST_CHECK_INTEGRAL_CONSTANT(::tt::is_nothrow_swappable<test_ns::only_adl_swappable[2]>::value, true);
BOOST_CHECK_INTEGRAL_CONSTANT(::tt::is_nothrow_swappable<test_ns::only_adl_swappable const[2]>::value, false);
BOOST_CHECK_INTEGRAL_CONSTANT(::tt::is_nothrow_swappable<test_ns::only_adl_swappable volatile[2]>::value, false);
BOOST_CHECK_INTEGRAL_CONSTANT(::tt::is_nothrow_swappable<test_ns::only_adl_swappable const volatile[2]>::value, false);
BOOST_CHECK_INTEGRAL_CONSTANT(::tt::is_nothrow_swappable<boost::type_traits_is_nothrow_swappable_test::swappable>::value, true);
BOOST_CHECK_INTEGRAL_CONSTANT(::tt::is_nothrow_swappable<boost::type_traits_is_nothrow_swappable_test::swappable const>::value, false);
BOOST_CHECK_INTEGRAL_CONSTANT(::tt::is_nothrow_swappable<boost::type_traits_is_nothrow_swappable_test::swappable volatile>::value, false);
BOOST_CHECK_INTEGRAL_CONSTANT(::tt::is_nothrow_swappable<boost::type_traits_is_nothrow_swappable_test::swappable const volatile>::value, false);
BOOST_CHECK_INTEGRAL_CONSTANT(::tt::is_nothrow_swappable<boost::type_traits_is_nothrow_swappable_test::swappable[2]>::value, true);
BOOST_CHECK_INTEGRAL_CONSTANT(::tt::is_nothrow_swappable<boost::type_traits_is_nothrow_swappable_test::swappable const[2]>::value, false);
BOOST_CHECK_INTEGRAL_CONSTANT(::tt::is_nothrow_swappable<boost::type_traits_is_nothrow_swappable_test::swappable volatile[2]>::value, false);
BOOST_CHECK_INTEGRAL_CONSTANT(::tt::is_nothrow_swappable<boost::type_traits_is_nothrow_swappable_test::swappable const volatile[2]>::value, false);
#endif // !defined(BOOST_NO_CXX11_DELETED_FUNCTIONS)
#endif
TT_TEST_END