From aa8dcb47cf46a1656edde03761c178cbc65010f7 Mon Sep 17 00:00:00 2001 From: Peter Dimov Date: Sat, 15 Jul 2017 18:57:34 +0300 Subject: [PATCH] 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