diff --git a/include/boost/type_traits/detail/is_swappable_cxx_11.hpp b/include/boost/type_traits/detail/is_swappable_cxx_11.hpp new file mode 100644 index 0000000..be22d1c --- /dev/null +++ b/include/boost/type_traits/detail/is_swappable_cxx_11.hpp @@ -0,0 +1,37 @@ +#ifndef BOOST_TYPE_TRAITS_DETAIL_IS_SWAPPABLE_CXX_11_HPP_INCLUDED +#define BOOST_TYPE_TRAITS_DETAIL_IS_SWAPPABLE_CXX_11_HPP_INCLUDED + +// Copyright 2017 Peter Dimov +// +// Distributed under the Boost Software License, Version 1.0. +// See accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt + +#include +#include +#include +#if __cplusplus >= 201103L || defined(BOOST_DINKUMWARE_STDLIB) +#include // for std::swap (C++11) +#else +#include // for std::swap (C++98) +#endif + +// Intentionally not within boost namespace to avoid implicitly pulling in boost::swap overloads other than through ADL +namespace boost_type_traits_swappable_detail +{ + +using std::swap; + +template(), boost::declval()))> boost::integral_constant is_nothrow_swappable_with_impl( int ); +template boost::false_type is_nothrow_swappable_with_impl( ... ); +template +struct is_nothrow_swappable_with_helper { typedef decltype( boost_type_traits_swappable_detail::is_nothrow_swappable_with_impl(0) ) type; }; + +template(), boost::declval()))> boost::integral_constant is_nothrow_swappable_impl( int ); +template boost::false_type is_nothrow_swappable_impl( ... ); +template +struct is_nothrow_swappable_helper { typedef decltype( boost_type_traits_swappable_detail::is_nothrow_swappable_impl(0) ) type; }; + +} // namespace boost_type_traits_swappable_detail + +#endif // #ifndef BOOST_TYPE_TRAITS_DETAIL_IS_SWAPPABLE_CXX_11_HPP_INCLUDED diff --git a/include/boost/type_traits/is_nothrow_swappable.hpp b/include/boost/type_traits/is_nothrow_swappable.hpp index 10ad923..fc319f7 100644 --- a/include/boost/type_traits/is_nothrow_swappable.hpp +++ b/include/boost/type_traits/is_nothrow_swappable.hpp @@ -28,35 +28,16 @@ template struct is_nothrow_swappable_with : is_nothrow_swappable #else -#include -#include -#include +#include namespace boost { -namespace type_traits_swappable_detail -{ - -using std::swap; - -template(), declval()))> integral_constant is_nothrow_swappable_with_impl( int ); -template false_type is_nothrow_swappable_with_impl( ... ); -template -struct is_nothrow_swappable_with_helper { typedef decltype( type_traits_swappable_detail::is_nothrow_swappable_with_impl(0) ) type; }; - -template(), declval()))> integral_constant is_nothrow_swappable_impl( int ); -template false_type is_nothrow_swappable_impl( ... ); -template -struct is_nothrow_swappable_helper { typedef decltype( type_traits_swappable_detail::is_nothrow_swappable_impl(0) ) type; }; - -} // namespace type_traits_swappable_detail - -template struct is_nothrow_swappable_with: type_traits_swappable_detail::is_nothrow_swappable_with_helper::type +template struct is_nothrow_swappable_with: boost_type_traits_swappable_detail::is_nothrow_swappable_with_helper::type { }; -template struct is_nothrow_swappable: type_traits_swappable_detail::is_nothrow_swappable_helper::type +template struct is_nothrow_swappable: boost_type_traits_swappable_detail::is_nothrow_swappable_helper::type { }; diff --git a/test/is_nothrow_swappable_test.cpp b/test/is_nothrow_swappable_test.cpp index a230896..fafa526 100644 --- a/test/is_nothrow_swappable_test.cpp +++ b/test/is_nothrow_swappable_test.cpp @@ -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 +// 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::value, true); @@ -52,9 +96,7 @@ BOOST_CHECK_INTEGRAL_CONSTANT(::tt::is_nothrow_swappable::value, fals BOOST_CHECK_INTEGRAL_CONSTANT(::tt::is_nothrow_swappable::value, true); BOOST_CHECK_INTEGRAL_CONSTANT(::tt::is_nothrow_swappable::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::value, false); BOOST_CHECK_INTEGRAL_CONSTANT(::tt::is_nothrow_swappable::value, false); BOOST_CHECK_INTEGRAL_CONSTANT(::tt::is_nothrow_swappable::value, false); @@ -71,9 +113,7 @@ BOOST_CHECK_INTEGRAL_CONSTANT(::tt::is_nothrow_swappable::value, fal BOOST_CHECK_INTEGRAL_CONSTANT(::tt::is_nothrow_swappable::value, false); BOOST_CHECK_INTEGRAL_CONSTANT(::tt::is_nothrow_swappable::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::value, false); BOOST_CHECK_INTEGRAL_CONSTANT(::tt::is_nothrow_swappable::value, false); @@ -157,6 +197,30 @@ BOOST_CHECK_INTEGRAL_CONSTANT((::tt::is_nothrow_swappable cons BOOST_CHECK_INTEGRAL_CONSTANT((::tt::is_nothrow_swappable volatile>::value), false); BOOST_CHECK_INTEGRAL_CONSTANT((::tt::is_nothrow_swappable const volatile>::value), false); +#if !defined(BOOST_NO_CXX11_DELETED_FUNCTIONS) + +BOOST_CHECK_INTEGRAL_CONSTANT(::tt::is_nothrow_swappable::value, true); +BOOST_CHECK_INTEGRAL_CONSTANT(::tt::is_nothrow_swappable::value, false); +BOOST_CHECK_INTEGRAL_CONSTANT(::tt::is_nothrow_swappable::value, false); +BOOST_CHECK_INTEGRAL_CONSTANT(::tt::is_nothrow_swappable::value, false); + +BOOST_CHECK_INTEGRAL_CONSTANT(::tt::is_nothrow_swappable::value, true); +BOOST_CHECK_INTEGRAL_CONSTANT(::tt::is_nothrow_swappable::value, false); +BOOST_CHECK_INTEGRAL_CONSTANT(::tt::is_nothrow_swappable::value, false); +BOOST_CHECK_INTEGRAL_CONSTANT(::tt::is_nothrow_swappable::value, false); + +BOOST_CHECK_INTEGRAL_CONSTANT(::tt::is_nothrow_swappable::value, true); +BOOST_CHECK_INTEGRAL_CONSTANT(::tt::is_nothrow_swappable::value, false); +BOOST_CHECK_INTEGRAL_CONSTANT(::tt::is_nothrow_swappable::value, false); +BOOST_CHECK_INTEGRAL_CONSTANT(::tt::is_nothrow_swappable::value, false); + +BOOST_CHECK_INTEGRAL_CONSTANT(::tt::is_nothrow_swappable::value, true); +BOOST_CHECK_INTEGRAL_CONSTANT(::tt::is_nothrow_swappable::value, false); +BOOST_CHECK_INTEGRAL_CONSTANT(::tt::is_nothrow_swappable::value, false); +BOOST_CHECK_INTEGRAL_CONSTANT(::tt::is_nothrow_swappable::value, false); + +#endif // !defined(BOOST_NO_CXX11_DELETED_FUNCTIONS) + #endif TT_TEST_END