From acf6e41edbcacf2cdc45311cdd29267a3a94b373 Mon Sep 17 00:00:00 2001 From: jzmaddock Date: Sat, 6 Jun 2015 12:51:51 +0100 Subject: [PATCH] Add is_assignable. Update has_nothrow_assign to make use of it. --- include/boost/type_traits.hpp | 2 + .../boost/type_traits/has_nothrow_assign.hpp | 29 ++-- include/boost/type_traits/intrinsics.hpp | 2 +- include/boost/type_traits/is_assignable.hpp | 76 +++++++++ test/has_nothrow_assign_test.cpp | 27 ++++ test/is_assignable_test.cpp | 151 ++++++++++++++++++ 6 files changed, 275 insertions(+), 12 deletions(-) create mode 100644 include/boost/type_traits/is_assignable.hpp create mode 100644 test/is_assignable_test.cpp diff --git a/include/boost/type_traits.hpp b/include/boost/type_traits.hpp index 4c9d8eb..cf35c68 100644 --- a/include/boost/type_traits.hpp +++ b/include/boost/type_traits.hpp @@ -41,6 +41,7 @@ #include "boost/type_traits/has_trivial_move_constructor.hpp" #include "boost/type_traits/has_virtual_destructor.hpp" #include "boost/type_traits/is_abstract.hpp" +#include "boost/type_traits/is_assignable.hpp" #include "boost/type_traits/is_arithmetic.hpp" #include "boost/type_traits/is_array.hpp" #include "boost/type_traits/is_base_and_derived.hpp" @@ -52,6 +53,7 @@ #include "boost/type_traits/is_convertible.hpp" #include "boost/type_traits/is_copy_constructible.hpp" #include "boost/type_traits/is_copy_assignable.hpp" +#include "boost/type_traits/is_default_constructible.hpp" #include "boost/type_traits/is_empty.hpp" #include "boost/type_traits/is_enum.hpp" #include "boost/type_traits/is_float.hpp" diff --git a/include/boost/type_traits/has_nothrow_assign.hpp b/include/boost/type_traits/has_nothrow_assign.hpp index c337fd6..c864eef 100644 --- a/include/boost/type_traits/has_nothrow_assign.hpp +++ b/include/boost/type_traits/has_nothrow_assign.hpp @@ -19,11 +19,14 @@ #include #include #include +#include +#include #endif #endif #if defined(__GNUC__) || defined(__SUNPRO_CC) #include #include +#include #ifdef BOOST_INTEL #include #endif @@ -35,28 +38,32 @@ namespace boost { namespace detail { - template struct has_nothrow_assign_imp{ static const bool value = false; }; - template struct has_nothrow_assign_imp{ static const bool value = noexcept(detail::tt_decl_ref() = detail::tt_decl_const_ref()); }; - template struct has_nothrow_assign_imp{ static const bool value = has_nothrow_assign_imp::value; }; - template struct has_nothrow_assign_imp{ static const bool value = has_nothrow_assign_imp::value; }; + template struct has_nothrow_assign_imp{ static const bool value = false; }; + template struct has_nothrow_assign_imp{ static const bool value = noexcept(detail::tt_decl_ref() = detail::tt_decl_const_ref()); }; + template struct has_nothrow_assign_imp{ static const bool value = has_nothrow_assign_imp::value; }; + template struct has_nothrow_assign_imp{ static const bool value = has_nothrow_assign_imp::value; }; } #endif -template -struct has_nothrow_assign : public integral_constant + struct has_nothrow_assign : public integral_constant < bool, #ifndef BOOST_HAS_NOTHROW_ASSIGN #if !defined(BOOST_NO_CXX11_NOEXCEPT) && !defined(BOOST_NO_SFINAE_EXPR) && !defined(BOOST_NO_CXX11_RVALUE_REFERENCES) - // Portable C++11 version: - detail::has_nothrow_assign_imp::type>::value || is_volatile::type>::value || is_reference::value>::value + // Portable C++11 version: + detail::has_nothrow_assign_imp::type>::value || is_volatile::type>::value || is_reference::value), + is_assignable::type, typename add_reference::type>::value + >::value #else - ::boost::has_trivial_assign::value + ::boost::has_trivial_assign::value #endif #else - BOOST_HAS_NOTHROW_ASSIGN(T) + BOOST_HAS_NOTHROW_ASSIGN(T) #endif ->{}; + > {}; +template struct has_nothrow_assign : public has_nothrow_assign {}; template <> struct has_nothrow_assign : public false_type{}; #ifndef BOOST_NO_CV_VOID_SPECIALIZATIONS template <> struct has_nothrow_assign : public false_type{}; diff --git a/include/boost/type_traits/intrinsics.hpp b/include/boost/type_traits/intrinsics.hpp index 1d66176..2d85f8b 100644 --- a/include/boost/type_traits/intrinsics.hpp +++ b/include/boost/type_traits/intrinsics.hpp @@ -245,7 +245,7 @@ # define BOOST_HAS_TRIVIAL_DESTRUCTOR(T) (__has_trivial_destructor(T) BOOST_INTEL_TT_OPTS) # define BOOST_HAS_NOTHROW_CONSTRUCTOR(T) (__has_nothrow_constructor(T) && is_default_constructible::value BOOST_INTEL_TT_OPTS) # define BOOST_HAS_NOTHROW_COPY(T) ((__has_nothrow_copy(T) BOOST_INTEL_TT_OPTS) && !is_volatile::value && !is_reference::value) -# define BOOST_HAS_NOTHROW_ASSIGN(T) ((__has_nothrow_assign(T) BOOST_INTEL_TT_OPTS) && !is_volatile::value && !is_const::value) +# define BOOST_HAS_NOTHROW_ASSIGN(T) ((__has_nothrow_assign(T) BOOST_INTEL_TT_OPTS) && !is_volatile::value && !is_const::value && is_assignable::value) # define BOOST_HAS_VIRTUAL_DESTRUCTOR(T) __has_virtual_destructor(T) # define BOOST_IS_ABSTRACT(T) __is_abstract(T) diff --git a/include/boost/type_traits/is_assignable.hpp b/include/boost/type_traits/is_assignable.hpp new file mode 100644 index 0000000..1095f80 --- /dev/null +++ b/include/boost/type_traits/is_assignable.hpp @@ -0,0 +1,76 @@ + +// (C) Copyright John Maddock 2015. +// Use, modification and distribution are subject to 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). +// +// See http://www.boost.org/libs/type_traits for most recent version including documentation. + +#ifndef BOOST_TT_IS_ASSIGNABLE_HPP_INCLUDED +#define BOOST_TT_IS_ASSIGNABLE_HPP_INCLUDED + +#include +#include + +namespace boost{ + + template struct is_assignable; + +} + +#if !defined(BOOST_NO_CXX11_DECLTYPE) && !BOOST_WORKAROUND(BOOST_MSVC, < 1800) + +#include +#include + +namespace boost{ + + namespace detail{ + + struct is_assignable_imp + { + template() = tt_declval())> + static boost::type_traits::yes_type test(int); + + template + static boost::type_traits::no_type test(...); + }; + + } + + template struct is_assignable : public integral_constant(0)) == sizeof(boost::type_traits::yes_type)>{}; + template struct is_assignable : public is_assignable{}; + template struct is_assignable : public is_assignable{}; + template struct is_assignable : public is_assignable{}; + template struct is_assignable : public is_assignable{}; + template struct is_assignable : public integral_constant{}; + template struct is_assignable : public integral_constant{}; + template struct is_assignable : public integral_constant{}; + template struct is_assignable : public integral_constant{}; + +#else + +#include +#include + +namespace boost{ + + // We don't know how to implement this: + template struct is_assignable : public integral_constant{}; + template struct is_assignable : public integral_constant::value && is_pod::type>::value>{}; + template struct is_assignable : public integral_constant{}; + template struct is_assignable : public integral_constant{}; + template struct is_assignable : public integral_constant{}; + template struct is_assignable : public integral_constant{}; + template struct is_assignable : public integral_constant{}; + /* + template <> struct is_assignable : public integral_constant{}; + template <> struct is_assignable : public integral_constant{}; + template <> struct is_assignable : public integral_constant{}; + template <> struct is_assignable : public integral_constant{}; + */ +#endif + +} // namespace boost + +#endif // BOOST_TT_IS_ASSIGNABLE_HPP_INCLUDED diff --git a/test/has_nothrow_assign_test.cpp b/test/has_nothrow_assign_test.cpp index ec3d110..ee221ee 100644 --- a/test/has_nothrow_assign_test.cpp +++ b/test/has_nothrow_assign_test.cpp @@ -12,6 +12,26 @@ # include #endif +#ifndef BOOST_NO_CXX11_DELETED_FUNCTIONS + +struct non_assignable +{ + non_assignable(); + non_assignable& operator=(const non_assignable&) = delete; +}; + +#endif + +#ifndef BOOST_NO_CXX11_NOEXCEPT + +struct noexcept_assignable +{ + noexcept_assignable(); + noexcept_assignable& operator=(const non_assignable&)noexcept; +}; + +#endif + TT_TEST_BEGIN(has_nothrow_assign) BOOST_CHECK_INTEGRAL_CONSTANT(::tt::has_nothrow_assign::value, true); @@ -205,6 +225,13 @@ BOOST_CHECK_INTEGRAL_CONSTANT(::tt::has_nothrow_assign::v BOOST_CHECK_INTEGRAL_CONSTANT(::tt::has_nothrow_assign::value, false); +#ifndef BOOST_NO_CXX11_DELETED_FUNCTIONS +BOOST_CHECK_INTEGRAL_CONSTANT(::tt::has_nothrow_assign::value, false); +#endif +#ifndef BOOST_NO_CXX11_NOEXCEPT +BOOST_CHECK_INTEGRAL_CONSTANT(::tt::has_nothrow_assign::value, true); +#endif + TT_TEST_END diff --git a/test/is_assignable_test.cpp b/test/is_assignable_test.cpp new file mode 100644 index 0000000..8a13ca2 --- /dev/null +++ b/test/is_assignable_test.cpp @@ -0,0 +1,151 @@ + +// (C) Copyright John Maddock 2000. +// Use, modification and distribution are subject to 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 "test.hpp" +#include "check_integral_constant.hpp" +#ifdef TEST_STD +# include +#else +# include +#endif + +#ifndef BOOST_NO_CXX11_DELETED_FUNCTIONS + +struct non_assignable +{ + non_assignable(); + non_assignable& operator=(const non_assignable&) = delete; +}; + +#endif + +#ifndef BOOST_NO_CXX11_NOEXCEPT + +struct noexcept_assignable +{ + noexcept_assignable(); + noexcept_assignable& operator=(const non_assignable&)noexcept; +}; + +#endif + +TT_TEST_BEGIN(is_assignable) + +BOOST_CHECK_INTEGRAL_CONSTANT((::tt::is_assignable::value), true); +#ifndef TEST_STD +// unspecified behaviour: +BOOST_CHECK_INTEGRAL_CONSTANT((::tt::is_assignable::value), false); +BOOST_CHECK_INTEGRAL_CONSTANT((::tt::is_assignable::value), true); +BOOST_CHECK_INTEGRAL_CONSTANT((::tt::is_assignable::value), false); +#endif + +BOOST_CHECK_INTEGRAL_CONSTANT((::tt::is_assignable::value), true); +#ifndef TEST_STD +// unspecified behaviour: +BOOST_CHECK_INTEGRAL_CONSTANT((::tt::is_assignable::value), false); +BOOST_CHECK_INTEGRAL_CONSTANT((::tt::is_assignable::value), true); +BOOST_CHECK_INTEGRAL_CONSTANT((::tt::is_assignable::value), false); +#endif +BOOST_CHECK_INTEGRAL_CONSTANT((::tt::is_assignable::value), true); +BOOST_CHECK_INTEGRAL_CONSTANT((::tt::is_assignable::value), true); + +BOOST_CHECK_INTEGRAL_CONSTANT((::tt::is_assignable::value), true); +BOOST_CHECK_INTEGRAL_CONSTANT((::tt::is_assignable::value), true); + +BOOST_CHECK_INTEGRAL_CONSTANT((::tt::is_assignable::value), true); +BOOST_CHECK_INTEGRAL_CONSTANT((::tt::is_assignable::value), true); +#ifndef TEST_STD +// unspecified behaviour: +BOOST_CHECK_INTEGRAL_CONSTANT((::tt::is_assignable::value), false); +BOOST_CHECK_INTEGRAL_CONSTANT((::tt::is_assignable::value), false); +BOOST_CHECK_INTEGRAL_CONSTANT((::tt::is_assignable::value), true); +BOOST_CHECK_INTEGRAL_CONSTANT((::tt::is_assignable::value), true); +BOOST_CHECK_INTEGRAL_CONSTANT((::tt::is_assignable::value), false); +BOOST_CHECK_INTEGRAL_CONSTANT((::tt::is_assignable::value), false); +#endif + +BOOST_CHECK_INTEGRAL_CONSTANT((::tt::is_assignable::value), true); +BOOST_CHECK_INTEGRAL_CONSTANT((::tt::is_assignable::value), true); +#ifndef TEST_STD +// unspecified behaviour: +BOOST_CHECK_INTEGRAL_CONSTANT((::tt::is_assignable::value), false); +BOOST_CHECK_INTEGRAL_CONSTANT((::tt::is_assignable::value), false); +BOOST_CHECK_INTEGRAL_CONSTANT((::tt::is_assignable::value), true); +BOOST_CHECK_INTEGRAL_CONSTANT((::tt::is_assignable::value), true); +BOOST_CHECK_INTEGRAL_CONSTANT((::tt::is_assignable::value), false); +BOOST_CHECK_INTEGRAL_CONSTANT((::tt::is_assignable::value), false); +#endif + +#ifdef BOOST_HAS_LONG_LONG + +BOOST_CHECK_INTEGRAL_CONSTANT((::tt::is_assignable< ::boost::ulong_long_type&>::value), true); +BOOST_CHECK_INTEGRAL_CONSTANT((::tt::is_assignable< ::boost::long_long_type&>::value), true); +#ifndef TEST_STD +// unspecified behaviour: +BOOST_CHECK_INTEGRAL_CONSTANT((::tt::is_assignable< ::boost::ulong_long_type const&>::value), false); +BOOST_CHECK_INTEGRAL_CONSTANT((::tt::is_assignable< ::boost::long_long_type const&>::value), false); +BOOST_CHECK_INTEGRAL_CONSTANT((::tt::is_assignable< ::boost::ulong_long_type volatile&>::value), true); +BOOST_CHECK_INTEGRAL_CONSTANT((::tt::is_assignable< ::boost::long_long_type volatile&>::value), true); +BOOST_CHECK_INTEGRAL_CONSTANT((::tt::is_assignable< ::boost::ulong_long_type const volatile&>::value), false); +BOOST_CHECK_INTEGRAL_CONSTANT((::tt::is_assignable< ::boost::long_long_type const volatile&>::value), false); +#endif +#endif + +BOOST_CHECK_INTEGRAL_CONSTANT((::tt::is_assignable::value), true); +#ifndef TEST_STD +// unspecified behaviour: +BOOST_CHECK_INTEGRAL_CONSTANT((::tt::is_assignable::value), false); +BOOST_CHECK_INTEGRAL_CONSTANT((::tt::is_assignable::value), true); +BOOST_CHECK_INTEGRAL_CONSTANT((::tt::is_assignable::value), false); +#endif + +BOOST_CHECK_INTEGRAL_CONSTANT((::tt::is_assignable::value), true); +#ifndef TEST_STD +// unspecified behaviour: +BOOST_CHECK_INTEGRAL_CONSTANT((::tt::is_assignable::value), false); +BOOST_CHECK_INTEGRAL_CONSTANT((::tt::is_assignable::value), true); +BOOST_CHECK_INTEGRAL_CONSTANT((::tt::is_assignable::value), false); +#endif + +BOOST_CHECK_INTEGRAL_CONSTANT((::tt::is_assignable::value), true); +#ifndef TEST_STD +// unspecified behaviour: +BOOST_CHECK_INTEGRAL_CONSTANT((::tt::is_assignable::value), false); +BOOST_CHECK_INTEGRAL_CONSTANT((::tt::is_assignable::value), true); +BOOST_CHECK_INTEGRAL_CONSTANT((::tt::is_assignable::value), false); +#endif + +BOOST_CHECK_INTEGRAL_CONSTANT((::tt::is_assignable::value), true); +#ifndef BOOST_NO_CXX11_RVALUE_REFERENCES +BOOST_CHECK_INTEGRAL_CONSTANT((::tt::is_assignable::value), true); +#endif +BOOST_CHECK_INTEGRAL_CONSTANT((::tt::is_assignable::value), false); +//BOOST_CHECK_INTEGRAL_CONSTANT((::tt::is_assignable::value), true); +//BOOST_CHECK_INTEGRAL_CONSTANT((::tt::is_assignable::value), true); +//BOOST_CHECK_INTEGRAL_CONSTANT((::tt::is_assignable::value), true); +BOOST_CHECK_SOFT_INTEGRAL_CONSTANT((::tt::is_assignable::value), true, false); +BOOST_CHECK_SOFT_INTEGRAL_CONSTANT((::tt::is_assignable::value), true, false); +BOOST_CHECK_INTEGRAL_CONSTANT((::tt::is_assignable::value), false); +// cases we would like to succeed but can't implement in the language: +BOOST_CHECK_SOFT_INTEGRAL_CONSTANT((::tt::is_assignable::value), true, false); +BOOST_CHECK_SOFT_INTEGRAL_CONSTANT((::tt::is_assignable::value), true, false); +BOOST_CHECK_SOFT_INTEGRAL_CONSTANT((::tt::is_assignable::value), true, false); +BOOST_CHECK_SOFT_INTEGRAL_CONSTANT((::tt::is_assignable::value), true, false); +BOOST_CHECK_SOFT_INTEGRAL_CONSTANT((::tt::is_assignable::value), true, false); + +BOOST_CHECK_SOFT_INTEGRAL_CONSTANT((::tt::is_assignable::value), true, false); + +#ifndef BOOST_NO_CXX11_DELETED_FUNCTIONS +BOOST_CHECK_INTEGRAL_CONSTANT((::tt::is_assignable::value), false); +#endif +#ifndef BOOST_NO_CXX11_NOEXCEPT +BOOST_CHECK_INTEGRAL_CONSTANT((::tt::is_assignable::value), true); +#endif + +TT_TEST_END + + +