From 2d713790742934dd629dc285ee83db795b7f8ee9 Mon Sep 17 00:00:00 2001 From: jzmaddock Date: Thu, 11 Jun 2015 10:00:09 +0100 Subject: [PATCH] Fix has_trivial* traits and improve their tests. --- .../boost/type_traits/has_trivial_assign.hpp | 22 ++++++----- .../type_traits/has_trivial_constructor.hpp | 3 +- .../type_traits/has_trivial_destructor.hpp | 4 ++ .../type_traits/has_trivial_move_assign.hpp | 4 ++ include/boost/type_traits/intrinsics.hpp | 21 ++++++---- .../type_traits/is_default_constructible.hpp | 7 ++-- test/has_trivial_assign_test.cpp | 29 ++++++++++++-- test/has_trivial_constr_test.cpp | 24 +++++++++++- test/has_trivial_copy_test.cpp | 8 ++++ test/has_trivial_destructor_test.cpp | 22 +++++++++++ test/has_trivial_move_assign_test.cpp | 37 ++++++++++++++++++ test/has_trivial_move_constructor_test.cpp | 38 +++++++++++++++++++ 12 files changed, 194 insertions(+), 25 deletions(-) diff --git a/include/boost/type_traits/has_trivial_assign.hpp b/include/boost/type_traits/has_trivial_assign.hpp index b67d009..5217c78 100644 --- a/include/boost/type_traits/has_trivial_assign.hpp +++ b/include/boost/type_traits/has_trivial_assign.hpp @@ -13,29 +13,33 @@ #include #include -#if !defined(BOOST_HAS_TRIVIAL_ASSIGN) || defined(BOOST_MSVC) || defined(__GNUC__) || defined(BOOST_INTEL) || defined(__SUNPRO_CC) +#if !defined(BOOST_HAS_TRIVIAL_ASSIGN) || defined(BOOST_MSVC) || defined(__GNUC__) || defined(BOOST_INTEL) || defined(__SUNPRO_CC) || defined(__clang) #include #include #include +#include #endif namespace boost { -template -struct has_trivial_assign : public integral_constant + struct has_trivial_assign : public integral_constant < bool, #ifdef BOOST_HAS_TRIVIAL_ASSIGN - BOOST_HAS_TRIVIAL_ASSIGN(T) + BOOST_HAS_TRIVIAL_ASSIGN(T) #else - ::boost::is_pod::value && !::boost::is_const::value && !::boost::is_volatile::value + ::boost::is_pod::value && !::boost::is_const::value && !::boost::is_volatile::value #endif > {}; -template<> struct has_trivial_assign : public false_type{}; + template<> struct has_trivial_assign : public false_type{}; #ifndef BOOST_NO_CV_VOID_SPECIALIZATIONS -template<> struct has_trivial_assign : public false_type{}; -template<> struct has_trivial_assign : public false_type{}; -template<> struct has_trivial_assign : public false_type{}; + template<> struct has_trivial_assign : public false_type{}; + template<> struct has_trivial_assign : public false_type{}; + template<> struct has_trivial_assign : public false_type{}; #endif + // Arrays are not explictly assignable: + template struct has_trivial_assign : public false_type{}; + template struct has_trivial_assign : public false_type{}; } // namespace boost diff --git a/include/boost/type_traits/has_trivial_constructor.hpp b/include/boost/type_traits/has_trivial_constructor.hpp index 24e581d..0f57aae 100644 --- a/include/boost/type_traits/has_trivial_constructor.hpp +++ b/include/boost/type_traits/has_trivial_constructor.hpp @@ -11,6 +11,7 @@ #include #include +#include #ifdef BOOST_HAS_TRIVIAL_CONSTRUCTOR #ifdef BOOST_HAS_SGI_TYPE_TRAITS @@ -27,7 +28,7 @@ namespace boost { template struct has_trivial_constructor #ifdef BOOST_HAS_TRIVIAL_CONSTRUCTOR - : public integral_constant ::value || BOOST_HAS_TRIVIAL_CONSTRUCTOR(T))>{}; + : public integral_constant ::value || BOOST_HAS_TRIVIAL_CONSTRUCTOR(T)) && is_default_constructible::value)>{}; #else : public integral_constant ::value>{}; #endif diff --git a/include/boost/type_traits/has_trivial_destructor.hpp b/include/boost/type_traits/has_trivial_destructor.hpp index dc1b24c..763283d 100644 --- a/include/boost/type_traits/has_trivial_destructor.hpp +++ b/include/boost/type_traits/has_trivial_destructor.hpp @@ -21,6 +21,10 @@ #include #endif +#if defined(__GNUC__) || defined(__clang) || defined(__SUNPRO_CC) +#include +#endif + namespace boost { template struct has_trivial_destructor : public integral_constant{}; diff --git a/include/boost/type_traits/has_trivial_move_assign.hpp b/include/boost/type_traits/has_trivial_move_assign.hpp index f291f6f..9235996 100644 --- a/include/boost/type_traits/has_trivial_move_assign.hpp +++ b/include/boost/type_traits/has_trivial_move_assign.hpp @@ -23,6 +23,10 @@ #endif #endif +#if defined(__GNUC__) || defined(__clang) +#include +#endif + namespace boost { template diff --git a/include/boost/type_traits/intrinsics.hpp b/include/boost/type_traits/intrinsics.hpp index 72095dc..3b4a047 100644 --- a/include/boost/type_traits/intrinsics.hpp +++ b/include/boost/type_traits/intrinsics.hpp @@ -174,10 +174,10 @@ # define BOOST_HAS_TRIVIAL_COPY(T) (__has_trivial_copy(T) && !is_reference::value) # endif # if __has_feature(has_trivial_assign) -# define BOOST_HAS_TRIVIAL_ASSIGN(T) (__has_trivial_assign(T) && !is_volatile::value) +# define BOOST_HAS_TRIVIAL_ASSIGN(T) (__has_trivial_assign(T) && !is_volatile::value && is_assignable::value) # endif # if __has_feature(has_trivial_destructor) -# define BOOST_HAS_TRIVIAL_DESTRUCTOR(T) __has_trivial_destructor(T) +# define BOOST_HAS_TRIVIAL_DESTRUCTOR(T) (__has_trivial_destructor(T) && is_destructible::value) # endif # if __has_feature(has_nothrow_constructor) # define BOOST_HAS_NOTHROW_CONSTRUCTOR(T) (__has_nothrow_constructor(T) && is_default_constructible::value) @@ -210,10 +210,10 @@ # define BOOST_IS_POLYMORPHIC(T) __is_polymorphic(T) # endif # if __has_feature(has_trivial_move_constructor) -# define BOOST_HAS_TRIVIAL_MOVE_CONSTRUCTOR(T) __has_trivial_move_constructor(T) +# define BOOST_HAS_TRIVIAL_MOVE_CONSTRUCTOR(T) (__has_trivial_move_constructor(T) && is_constructible::value) # endif # if __has_feature(has_trivial_move_assign) -# define BOOST_HAS_TRIVIAL_MOVE_ASSIGN(T) __has_trivial_move_assign(T) +# define BOOST_HAS_TRIVIAL_MOVE_ASSIGN(T) (__has_trivial_move_assign(T) && is_assignable::value) # endif # define BOOST_ALIGNMENT_OF(T) __alignof(T) # if __has_feature(is_final) @@ -241,8 +241,8 @@ # define BOOST_IS_EMPTY(T) __is_empty(T) # define BOOST_HAS_TRIVIAL_CONSTRUCTOR(T) ((__has_trivial_constructor(T) BOOST_INTEL_TT_OPTS) && ! ::boost::is_volatile::value) # define BOOST_HAS_TRIVIAL_COPY(T) ((__has_trivial_copy(T) BOOST_INTEL_TT_OPTS) && !is_reference::value) -# define BOOST_HAS_TRIVIAL_ASSIGN(T) ((__has_trivial_assign(T) BOOST_INTEL_TT_OPTS) && ! ::boost::is_volatile::value && ! ::boost::is_const::value) -# define BOOST_HAS_TRIVIAL_DESTRUCTOR(T) (__has_trivial_destructor(T) BOOST_INTEL_TT_OPTS) +# define BOOST_HAS_TRIVIAL_ASSIGN(T) ((__has_trivial_assign(T) BOOST_INTEL_TT_OPTS) && ! ::boost::is_volatile::value && ! ::boost::is_const::value && is_assignable::value) +# define BOOST_HAS_TRIVIAL_DESTRUCTOR(T) (__has_trivial_destructor(T) BOOST_INTEL_TT_OPTS && is_destructible::value) # 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 && is_constructible::value) # define BOOST_HAS_NOTHROW_ASSIGN(T) ((__has_nothrow_assign(T) BOOST_INTEL_TT_OPTS) && !is_volatile::value && !is_const::value && is_assignable::value) @@ -263,6 +263,11 @@ # define BOOST_IS_FINAL(T) __is_final(T) # endif +# if __GNUC__ >= 5 +# define BOOST_HAS_TRIVIAL_MOVE_ASSIGN(T) (__is_trivially_assignable(T&, T&&) && is_assignable::value) +# define BOOST_HAS_TRIVIAL_MOVE_CONSTRUCTOR(T) (__is_trivially_constructible(T, T&&) && is_constructible::value) +# endif + # define BOOST_HAS_TYPE_TRAITS_INTRINSICS #endif @@ -276,8 +281,8 @@ # define BOOST_IS_EMPTY(T) __oracle_is_empty(T) # define BOOST_HAS_TRIVIAL_CONSTRUCTOR(T) (__oracle_has_trivial_constructor(T) && ! ::boost::is_volatile::value) # define BOOST_HAS_TRIVIAL_COPY(T) (__oracle_has_trivial_copy(T) && !is_reference::value) -# define BOOST_HAS_TRIVIAL_ASSIGN(T) ((__oracle_has_trivial_assign(T) || __oracle_is_trivial(T)) && ! ::boost::is_volatile::value && ! ::boost::is_const::value) -# define BOOST_HAS_TRIVIAL_DESTRUCTOR(T) __oracle_has_trivial_destructor(T) +# define BOOST_HAS_TRIVIAL_ASSIGN(T) ((__oracle_has_trivial_assign(T) || __oracle_is_trivial(T)) && ! ::boost::is_volatile::value && ! ::boost::is_const::value && is_assignable::value) +# define BOOST_HAS_TRIVIAL_DESTRUCTOR(T) (__oracle_has_trivial_destructor(T) && is_destructible::value) # define BOOST_HAS_NOTHROW_CONSTRUCTOR(T) ((__oracle_has_nothrow_constructor(T) || __oracle_has_trivial_constructor(T) || __oracle_is_trivial(T)) && is_default_constructible::value) # define BOOST_HAS_NOTHROW_COPY(T) ((__oracle_has_nothrow_copy(T) || __oracle_has_trivial_copy(T) || __oracle_is_trivial(T)) && !is_volatile::value && !is_reference::value) # define BOOST_HAS_NOTHROW_ASSIGN(T) ((__oracle_has_nothrow_assign(T) || __oracle_has_trivial_assign(T) || __oracle_is_trivial(T)) && !is_volatile::value && !is_const::value) diff --git a/include/boost/type_traits/is_default_constructible.hpp b/include/boost/type_traits/is_default_constructible.hpp index 48ed772..769e360 100644 --- a/include/boost/type_traits/is_default_constructible.hpp +++ b/include/boost/type_traits/is_default_constructible.hpp @@ -43,12 +43,13 @@ namespace boost{ #else -#include +#include namespace boost{ - // We don't know how to implement this: - template struct is_default_constructible : public has_trivial_constructor{}; + // We don't know how to implement this, note we can not use has_trivial_constructor here + // because the correct implementation of that trait requires this one: + template struct is_default_constructible : public is_pod{}; template <> struct is_default_constructible : public integral_constant{}; template <> struct is_default_constructible : public integral_constant{}; template <> struct is_default_constructible : public integral_constant{}; diff --git a/test/has_trivial_assign_test.cpp b/test/has_trivial_assign_test.cpp index cc8ad45..c5e40a3 100644 --- a/test/has_trivial_assign_test.cpp +++ b/test/has_trivial_assign_test.cpp @@ -12,6 +12,23 @@ # include #endif +struct non_assignable +{ + non_assignable(); +private: + non_assignable& operator=(const non_assignable&); +}; + +#ifndef BOOST_NO_CXX11_DELETED_FUNCTIONS + +struct non_assignable2 +{ + non_assignable2(); + non_assignable2& operator=(const non_assignable2&) = delete; +}; + +#endif + TT_TEST_BEGIN(has_trivial_assign) BOOST_CHECK_INTEGRAL_CONSTANT(::tt::has_trivial_assign::value, true); @@ -180,9 +197,10 @@ BOOST_CHECK_INTEGRAL_CONSTANT(::tt::has_trivial_assign::value, false); BOOST_CHECK_INTEGRAL_CONSTANT(::tt::has_trivial_assign::value, false); #endif BOOST_CHECK_INTEGRAL_CONSTANT(::tt::has_trivial_assign::value, false); -BOOST_CHECK_INTEGRAL_CONSTANT(::tt::has_trivial_assign::value, true); -BOOST_CHECK_INTEGRAL_CONSTANT(::tt::has_trivial_assign::value, true); -BOOST_CHECK_INTEGRAL_CONSTANT(::tt::has_trivial_assign::value, true); +// Arrays can not be explicitly assigned: +BOOST_CHECK_INTEGRAL_CONSTANT(::tt::has_trivial_assign::value, false); +BOOST_CHECK_INTEGRAL_CONSTANT(::tt::has_trivial_assign::value, false); +BOOST_CHECK_INTEGRAL_CONSTANT(::tt::has_trivial_assign::value, false); BOOST_CHECK_INTEGRAL_CONSTANT(::tt::has_trivial_assign::value, false); BOOST_CHECK_INTEGRAL_CONSTANT(::tt::has_trivial_assign::value, false); BOOST_CHECK_INTEGRAL_CONSTANT(::tt::has_trivial_assign::value, false); @@ -203,6 +221,11 @@ BOOST_CHECK_SOFT_INTEGRAL_CONSTANT(::tt::has_trivial_assign::value, false); +#ifndef BOOST_NO_CXX11_DELETED_FUNCTIONS +BOOST_CHECK_INTEGRAL_CONSTANT(::tt::has_trivial_assign::value, false); +#endif +BOOST_CHECK_INTEGRAL_CONSTANT(::tt::has_trivial_assign::value, false); + TT_TEST_END diff --git a/test/has_trivial_constr_test.cpp b/test/has_trivial_constr_test.cpp index 8db4ede..16a4e8a 100644 --- a/test/has_trivial_constr_test.cpp +++ b/test/has_trivial_constr_test.cpp @@ -27,6 +27,22 @@ public: explicit bug11324_derived(char arg) : data(arg) {} }; +struct private_construct +{ + private_construct(int); +private: + private_construct(); +}; + +#ifndef BOOST_NO_CXX11_DELETED_FUNCTIONS + +struct deleted_construct +{ + deleted_construct(int); + deleted_construct() = delete; +}; + +#endif TT_TEST_BEGIN(has_trivial_constructor) @@ -167,7 +183,8 @@ BOOST_CHECK_INTEGRAL_CONSTANT(::tt::has_trivial_constructor::value, t BOOST_CHECK_INTEGRAL_CONSTANT(::tt::has_trivial_constructor::value, true); BOOST_CHECK_INTEGRAL_CONSTANT(::tt::has_trivial_constructor::value, false); BOOST_CHECK_INTEGRAL_CONSTANT(::tt::has_trivial_constructor::value, false); -BOOST_CHECK_INTEGRAL_CONSTANT(::tt::has_trivial_constructor::value, true); +// Can't construct type void: +BOOST_CHECK_INTEGRAL_CONSTANT(::tt::has_trivial_constructor::value, false); // cases we would like to succeed but can't implement in the language: BOOST_CHECK_SOFT_INTEGRAL_CONSTANT(::tt::has_trivial_constructor::value, true, false); BOOST_CHECK_SOFT_INTEGRAL_CONSTANT(::tt::has_trivial_constructor::value, true, false); @@ -187,6 +204,11 @@ BOOST_CHECK_SOFT_INTEGRAL_CONSTANT(::tt::has_trivial_constructor::value, false); BOOST_CHECK_INTEGRAL_CONSTANT(::tt::has_trivial_constructor::value, false); +BOOST_CHECK_INTEGRAL_CONSTANT(::tt::has_trivial_constructor::value, false); +#ifndef BOOST_NO_CXX11_DELETED_FUNCTIONS +BOOST_CHECK_INTEGRAL_CONSTANT(::tt::has_trivial_constructor::value, false); +#endif + TT_TEST_END diff --git a/test/has_trivial_copy_test.cpp b/test/has_trivial_copy_test.cpp index 6a803b8..043f76e 100644 --- a/test/has_trivial_copy_test.cpp +++ b/test/has_trivial_copy_test.cpp @@ -25,6 +25,13 @@ public: #endif +struct private_copy +{ + private_copy(); +private: + private_copy(const private_copy&); +}; + TT_TEST_BEGIN(has_trivial_copy) BOOST_CHECK_INTEGRAL_CONSTANT(::tt::has_trivial_copy::value, true); @@ -220,6 +227,7 @@ BOOST_CHECK_INTEGRAL_CONSTANT(::tt::has_trivial_copy::value, false); #ifndef BOOST_NO_CXX11_DELETED_FUNCTIONS BOOST_CHECK_INTEGRAL_CONSTANT(::tt::has_trivial_copy::value, false); #endif +BOOST_CHECK_INTEGRAL_CONSTANT(::tt::has_trivial_copy::value, false); TT_TEST_END diff --git a/test/has_trivial_destructor_test.cpp b/test/has_trivial_destructor_test.cpp index 48196b7..3792004 100644 --- a/test/has_trivial_destructor_test.cpp +++ b/test/has_trivial_destructor_test.cpp @@ -12,6 +12,23 @@ # include #endif +#ifndef BOOST_NO_CXX11_DELETED_FUNCTIONS + +struct deleted_destruct +{ + deleted_destruct(); + ~deleted_destruct() = delete; +}; + +#endif + +struct private_destruct +{ + private_destruct(); +private: + ~private_destruct(); +}; + TT_TEST_BEGIN(has_trivial_destructor) BOOST_CHECK_INTEGRAL_CONSTANT(::tt::has_trivial_destructor::value, true); @@ -170,6 +187,11 @@ BOOST_CHECK_SOFT_INTEGRAL_CONSTANT(::tt::has_trivial_destructor >::value, true, false); BOOST_CHECK_SOFT_INTEGRAL_CONSTANT(::tt::has_trivial_destructor >::value, true, false); +BOOST_CHECK_INTEGRAL_CONSTANT(::tt::has_trivial_destructor::value, false); +#ifndef BOOST_NO_CXX11_DELETED_FUNCTIONS +BOOST_CHECK_INTEGRAL_CONSTANT(::tt::has_trivial_destructor::value, false); +#endif + TT_TEST_END diff --git a/test/has_trivial_move_assign_test.cpp b/test/has_trivial_move_assign_test.cpp index d54fcdc..009867f 100644 --- a/test/has_trivial_move_assign_test.cpp +++ b/test/has_trivial_move_assign_test.cpp @@ -13,6 +13,38 @@ # include #endif +#ifndef BOOST_NO_CXX11_DELETED_FUNCTIONS + +struct non_copyable_movable +{ + int val; + non_copyable_movable(int); + non_copyable_movable(const non_copyable_movable&) = delete; + non_copyable_movable& operator=(const non_copyable_movable&) = delete; + //non_copyable_movable(non_copyable_movable&&) = default; +#if BOOST_WORKAROUND(BOOST_MSVC, <= 1800) + non_copyable_movable& operator=(non_copyable_movable&& o) + { + val = std::move(o.val); + return *this; + } +#else + non_copyable_movable& operator=(non_copyable_movable&&) = default; +#endif +}; + +struct copyable_non_moveable +{ + int val; + copyable_non_moveable(int); + copyable_non_moveable(const copyable_non_moveable&) = default; + copyable_non_moveable& operator=(const copyable_non_moveable&) = default; + copyable_non_moveable(copyable_non_moveable&&) = delete; + copyable_non_moveable& operator=(copyable_non_moveable&&) = delete; +}; + +#endif + TT_TEST_BEGIN(has_trivial_move_assign) BOOST_CHECK_INTEGRAL_CONSTANT(::tt::has_trivial_move_assign::value, true); @@ -204,6 +236,11 @@ BOOST_CHECK_SOFT_INTEGRAL_CONSTANT(::tt::has_trivial_move_assign::value, false); +#ifndef BOOST_NO_CXX11_DELETED_FUNCTIONS +BOOST_CHECK_SOFT_INTEGRAL_CONSTANT(::tt::has_trivial_move_assign::value, true, false); +BOOST_CHECK_INTEGRAL_CONSTANT(::tt::has_trivial_move_assign::value, false); +#endif + TT_TEST_END diff --git a/test/has_trivial_move_constructor_test.cpp b/test/has_trivial_move_constructor_test.cpp index 472df99..1071f1b 100644 --- a/test/has_trivial_move_constructor_test.cpp +++ b/test/has_trivial_move_constructor_test.cpp @@ -13,6 +13,39 @@ # include #endif +#ifndef BOOST_NO_CXX11_DELETED_FUNCTIONS + +struct non_copyable_movable +{ + int val; + non_copyable_movable(int); + non_copyable_movable(const non_copyable_movable&) = delete; + non_copyable_movable& operator=(const non_copyable_movable&) = delete; +#if BOOST_WORKAROUND(BOOST_MSVC, <= 1800) + non_copyable_movable(non_copyable_movable&& o) : val(o.val){} + non_copyable_movable& operator=(non_copyable_movable&& o) + { + val = std::move(o.val); + return *this; + } +#else + non_copyable_movable(non_copyable_movable&&) = default; + non_copyable_movable& operator=(non_copyable_movable&&) = default; +#endif +}; + +struct copyable_non_moveable +{ + int val; + copyable_non_moveable(int); + copyable_non_moveable(const copyable_non_moveable&) = default; + copyable_non_moveable& operator=(const copyable_non_moveable&) = default; + copyable_non_moveable(copyable_non_moveable&&) = delete; + copyable_non_moveable& operator=(copyable_non_moveable&&) = delete; +}; + +#endif + TT_TEST_BEGIN(has_trivial_move_constructor) BOOST_CHECK_INTEGRAL_CONSTANT(::tt::has_trivial_move_constructor::value, true); @@ -204,6 +237,11 @@ BOOST_CHECK_SOFT_INTEGRAL_CONSTANT(::tt::has_trivial_move_constructor::value, false); +#ifndef BOOST_NO_CXX11_DELETED_FUNCTIONS +BOOST_CHECK_SOFT_INTEGRAL_CONSTANT(::tt::has_trivial_move_constructor::value, true, false); +BOOST_CHECK_INTEGRAL_CONSTANT(::tt::has_trivial_move_constructor::value, false); +#endif + TT_TEST_END