From aa8dcb47cf46a1656edde03761c178cbc65010f7 Mon Sep 17 00:00:00 2001 From: Peter Dimov Date: Sat, 15 Jul 2017 18:57:34 +0300 Subject: [PATCH 1/3] Add is_nothrow_swappable --- doc/is_nothrow_swappable.qbk | 23 +++ doc/type_traits.qbk | 2 + include/boost/type_traits.hpp | 1 + .../type_traits/is_nothrow_swappable.hpp | 47 ++++++ test/is_nothrow_swappable_test.cpp | 135 ++++++++++++++++++ 5 files changed, 208 insertions(+) create mode 100644 doc/is_nothrow_swappable.qbk create mode 100644 include/boost/type_traits/is_nothrow_swappable.hpp create mode 100644 test/is_nothrow_swappable_test.cpp diff --git a/doc/is_nothrow_swappable.qbk b/doc/is_nothrow_swappable.qbk new file mode 100644 index 0000000..8e5886e --- /dev/null +++ b/doc/is_nothrow_swappable.qbk @@ -0,0 +1,23 @@ +[/ + 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). +] + +[section:is_nothrow_swappable is_nothrow_swappable] + + template + struct is_nothrow_swappable : public __tof {}; + +__inherit If the expression `swap(declval(), declval())` (in a context +where `std::swap` is visible) is valid and non-throwing, inherits from +__true_type, otherwise from __false_type. + +__compat This trait requires C++11. + +__header ` #include ` or ` #include ` + +[endsect] diff --git a/doc/type_traits.qbk b/doc/type_traits.qbk index 1a1fa5b..5dea9ad 100644 --- a/doc/type_traits.qbk +++ b/doc/type_traits.qbk @@ -100,6 +100,7 @@ [def __is_nothrow_move_constructible [link boost_typetraits.reference.is_nothrow_move_constructible is_nothrow_move_constructible]] [def __has_nothrow_assign [link boost_typetraits.reference.has_nothrow_assign has_nothrow_assign]] [def __is_nothrow_move_assignable [link boost_typetraits.reference.is_nothrow_move_assignable is_nothrow_move_assignable]] +[def __is_nothrow_swappable [link boost_typetraits.reference.is_nothrow_swappable is_nothrow_swappable]] [def __is_base_of [link boost_typetraits.reference.is_base_of is_base_of]] [def __is_virtual_base_of [link boost_typetraits.reference.is_virtual_base_of is_virtual_base_of]] @@ -300,6 +301,7 @@ See __has_trivial_constructor. [include is_member_pointer.qbk] [include is_nothrow_move_assignable.qbk] [include is_nothrow_move_constructible.qbk] +[include is_nothrow_swappable.qbk] [include is_object.qbk] [include is_pod.qbk] [include is_pointer.qbk] diff --git a/include/boost/type_traits.hpp b/include/boost/type_traits.hpp index dbc8c95..0e6a7aa 100644 --- a/include/boost/type_traits.hpp +++ b/include/boost/type_traits.hpp @@ -113,6 +113,7 @@ #include #include #include +#include #include #include #include diff --git a/include/boost/type_traits/is_nothrow_swappable.hpp b/include/boost/type_traits/is_nothrow_swappable.hpp new file mode 100644 index 0000000..b355664 --- /dev/null +++ b/include/boost/type_traits/is_nothrow_swappable.hpp @@ -0,0 +1,47 @@ +#ifndef BOOST_TYPE_TRAITS_IS_NOTHROW_SWAPPABLE_HPP_INCLUDED +#define BOOST_TYPE_TRAITS_IS_NOTHROW_SWAPPABLE_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 + +#if defined(BOOST_NO_SFINAE_EXPR) || defined(BOOST_NO_CXX11_NOEXCEPT) || defined(BOOST_NO_CXX11_DECLTYPE) || defined(BOOST_NO_CXX11_FUNCTION_TEMPLATE_DEFAULT_ARGS) +#else + +#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(), declval()))> integral_constant is_nothrow_swappable_impl( int ); +template false_type is_nothrow_swappable_impl( ... ); + +} // namespace type_traits_swappable_detail + +template struct is_nothrow_swappable_with: decltype( type_traits_swappable_detail::is_nothrow_swappable_with_impl(0) ) +{ +}; + +template struct is_nothrow_swappable: decltype( type_traits_swappable_detail::is_nothrow_swappable_impl(0) ) +{ +}; + +} // namespace boost + +#endif + +#endif // #ifndef BOOST_TYPE_TRAITS_IS_NOTHROW_SWAPPABLE_HPP_INCLUDED diff --git a/test/is_nothrow_swappable_test.cpp b/test/is_nothrow_swappable_test.cpp new file mode 100644 index 0000000..52915b6 --- /dev/null +++ b/test/is_nothrow_swappable_test.cpp @@ -0,0 +1,135 @@ + +// 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 + +#ifdef TEST_STD +# include +#else +# include +#endif + +#include + +#if defined(BOOST_NO_SFINAE_EXPR) || defined(BOOST_NO_CXX11_NOEXCEPT) || defined(BOOST_NO_CXX11_DECLTYPE) || defined(BOOST_NO_CXX11_FUNCTION_TEMPLATE_DEFAULT_ARGS) + +int main() +{ +} + +#else + +#include "test.hpp" +#include "check_integral_constant.hpp" +#include +#include + +struct X +{ +}; + +struct Y +{ + Y( Y const& ) {} +}; + +struct Z +{ + Z& operator=( Z const& ) { return *this; } +}; + +struct V +{ + V( V const& ) {} + V& operator=( V const& ) { return *this; } +}; + +void swap( V&, V& ) noexcept {} + +TT_TEST_BEGIN(is_nothrow_swappable) + +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, true); +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, 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, 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, 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, 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, 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, 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, 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, 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 const>::value, false); +BOOST_CHECK_INTEGRAL_CONSTANT(::tt::is_nothrow_swappable volatile>::value, false); +BOOST_CHECK_INTEGRAL_CONSTANT(::tt::is_nothrow_swappable const volatile>::value, false); + +BOOST_CHECK_INTEGRAL_CONSTANT(::tt::is_nothrow_swappable >::value, true); +BOOST_CHECK_INTEGRAL_CONSTANT(::tt::is_nothrow_swappable const>::value, false); +BOOST_CHECK_INTEGRAL_CONSTANT(::tt::is_nothrow_swappable volatile>::value, false); +BOOST_CHECK_INTEGRAL_CONSTANT(::tt::is_nothrow_swappable const volatile>::value, false); + +BOOST_CHECK_INTEGRAL_CONSTANT((::tt::is_nothrow_swappable >::value), true); +BOOST_CHECK_INTEGRAL_CONSTANT((::tt::is_nothrow_swappable const>::value), false); +BOOST_CHECK_INTEGRAL_CONSTANT((::tt::is_nothrow_swappable volatile>::value), false); +BOOST_CHECK_INTEGRAL_CONSTANT((::tt::is_nothrow_swappable const volatile>::value), false); + +BOOST_CHECK_INTEGRAL_CONSTANT((::tt::is_nothrow_swappable >::value), false); +BOOST_CHECK_INTEGRAL_CONSTANT((::tt::is_nothrow_swappable const>::value), false); +BOOST_CHECK_INTEGRAL_CONSTANT((::tt::is_nothrow_swappable volatile>::value), false); +BOOST_CHECK_INTEGRAL_CONSTANT((::tt::is_nothrow_swappable const volatile>::value), false); + +BOOST_CHECK_INTEGRAL_CONSTANT((::tt::is_nothrow_swappable >::value), true); +BOOST_CHECK_INTEGRAL_CONSTANT((::tt::is_nothrow_swappable const>::value), false); +BOOST_CHECK_INTEGRAL_CONSTANT((::tt::is_nothrow_swappable volatile>::value), false); +BOOST_CHECK_INTEGRAL_CONSTANT((::tt::is_nothrow_swappable const volatile>::value), false); + +TT_TEST_END + +#endif From 1154c16b34dccf61014ce112b141a65828554d44 Mon Sep 17 00:00:00 2001 From: Peter Dimov Date: Sat, 15 Jul 2017 20:41:23 +0300 Subject: [PATCH 2/3] std::vector isn't nothrow swappable pre-C++17 --- test/is_nothrow_swappable_test.cpp | 11 ----------- 1 file changed, 11 deletions(-) diff --git a/test/is_nothrow_swappable_test.cpp b/test/is_nothrow_swappable_test.cpp index 52915b6..914bd62 100644 --- a/test/is_nothrow_swappable_test.cpp +++ b/test/is_nothrow_swappable_test.cpp @@ -23,7 +23,6 @@ int main() #include "test.hpp" #include "check_integral_constant.hpp" -#include #include struct X @@ -105,16 +104,6 @@ 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); -BOOST_CHECK_INTEGRAL_CONSTANT(::tt::is_nothrow_swappable >::value, true); -BOOST_CHECK_INTEGRAL_CONSTANT(::tt::is_nothrow_swappable const>::value, false); -BOOST_CHECK_INTEGRAL_CONSTANT(::tt::is_nothrow_swappable volatile>::value, false); -BOOST_CHECK_INTEGRAL_CONSTANT(::tt::is_nothrow_swappable const volatile>::value, false); - -BOOST_CHECK_INTEGRAL_CONSTANT(::tt::is_nothrow_swappable >::value, true); -BOOST_CHECK_INTEGRAL_CONSTANT(::tt::is_nothrow_swappable const>::value, false); -BOOST_CHECK_INTEGRAL_CONSTANT(::tt::is_nothrow_swappable volatile>::value, false); -BOOST_CHECK_INTEGRAL_CONSTANT(::tt::is_nothrow_swappable const volatile>::value, false); - BOOST_CHECK_INTEGRAL_CONSTANT((::tt::is_nothrow_swappable >::value), true); BOOST_CHECK_INTEGRAL_CONSTANT((::tt::is_nothrow_swappable const>::value), false); BOOST_CHECK_INTEGRAL_CONSTANT((::tt::is_nothrow_swappable volatile>::value), false); From b47d4aa421b3cc6c05568c4f061f7427de4be690 Mon Sep 17 00:00:00 2001 From: Peter Dimov Date: Sat, 15 Jul 2017 21:32:13 +0300 Subject: [PATCH 3/3] Disable is_nothrow_swappable_test for the built-in clang++ on Travis, libstdc++ 4.6 is too old --- test/is_nothrow_swappable_test.cpp | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/test/is_nothrow_swappable_test.cpp b/test/is_nothrow_swappable_test.cpp index 914bd62..1377c8a 100644 --- a/test/is_nothrow_swappable_test.cpp +++ b/test/is_nothrow_swappable_test.cpp @@ -13,7 +13,8 @@ #include -#if defined(BOOST_NO_SFINAE_EXPR) || defined(BOOST_NO_CXX11_NOEXCEPT) || defined(BOOST_NO_CXX11_DECLTYPE) || defined(BOOST_NO_CXX11_FUNCTION_TEMPLATE_DEFAULT_ARGS) +#if defined(BOOST_NO_SFINAE_EXPR) || defined(BOOST_NO_CXX11_NOEXCEPT) || defined(BOOST_NO_CXX11_DECLTYPE) || defined(BOOST_NO_CXX11_FUNCTION_TEMPLATE_DEFAULT_ARGS) \ + || (defined(__GLIBCXX__) && __GLIBCXX__ <= 20120301) // built-in clang++ -std=c++11 on Travis, w/ libstdc++ 4.6 int main() {