Fix has_trivial* traits and improve their tests.

This commit is contained in:
jzmaddock
2015-06-11 10:00:09 +01:00
parent 24548d6158
commit 2d71379074
12 changed files with 194 additions and 25 deletions

View File

@ -13,29 +13,33 @@
#include <boost/type_traits/intrinsics.hpp>
#include <boost/type_traits/integral_constant.hpp>
#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 <boost/type_traits/is_pod.hpp>
#include <boost/type_traits/is_const.hpp>
#include <boost/type_traits/is_volatile.hpp>
#include <boost/type_traits/is_assignable.hpp>
#endif
namespace boost {
template <typename T>
struct has_trivial_assign : public integral_constant<bool,
template <typename T>
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<T>::value && !::boost::is_const<T>::value && !::boost::is_volatile<T>::value
::boost::is_pod<T>::value && !::boost::is_const<T>::value && !::boost::is_volatile<T>::value
#endif
> {};
template<> struct has_trivial_assign<void> : public false_type{};
template<> struct has_trivial_assign<void> : public false_type{};
#ifndef BOOST_NO_CV_VOID_SPECIALIZATIONS
template<> struct has_trivial_assign<void const> : public false_type{};
template<> struct has_trivial_assign<void const volatile> : public false_type{};
template<> struct has_trivial_assign<void volatile> : public false_type{};
template<> struct has_trivial_assign<void const> : public false_type{};
template<> struct has_trivial_assign<void const volatile> : public false_type{};
template<> struct has_trivial_assign<void volatile> : public false_type{};
#endif
// Arrays are not explictly assignable:
template <typename T, std::size_t N> struct has_trivial_assign<T[N]> : public false_type{};
template <typename T> struct has_trivial_assign<T[]> : public false_type{};
} // namespace boost

View File

@ -11,6 +11,7 @@
#include <boost/type_traits/intrinsics.hpp>
#include <boost/type_traits/is_pod.hpp>
#include <boost/type_traits/is_default_constructible.hpp>
#ifdef BOOST_HAS_TRIVIAL_CONSTRUCTOR
#ifdef BOOST_HAS_SGI_TYPE_TRAITS
@ -27,7 +28,7 @@ namespace boost {
template <typename T> struct has_trivial_constructor
#ifdef BOOST_HAS_TRIVIAL_CONSTRUCTOR
: public integral_constant <bool, (::boost::is_pod<T>::value || BOOST_HAS_TRIVIAL_CONSTRUCTOR(T))>{};
: public integral_constant <bool, ((::boost::is_pod<T>::value || BOOST_HAS_TRIVIAL_CONSTRUCTOR(T)) && is_default_constructible<T>::value)>{};
#else
: public integral_constant <bool, ::boost::is_pod<T>::value>{};
#endif

View File

@ -21,6 +21,10 @@
#include <boost/type_traits/is_same.hpp>
#endif
#if defined(__GNUC__) || defined(__clang) || defined(__SUNPRO_CC)
#include <boost/type_traits/is_destructible.hpp>
#endif
namespace boost {
template <typename T> struct has_trivial_destructor : public integral_constant<bool, BOOST_HAS_TRIVIAL_DESTRUCTOR(T)>{};

View File

@ -23,6 +23,10 @@
#endif
#endif
#if defined(__GNUC__) || defined(__clang)
#include <boost/type_traits/is_assignable.hpp>
#endif
namespace boost {
template <typename T>

View File

@ -174,10 +174,10 @@
# define BOOST_HAS_TRIVIAL_COPY(T) (__has_trivial_copy(T) && !is_reference<T>::value)
# endif
# if __has_feature(has_trivial_assign)
# define BOOST_HAS_TRIVIAL_ASSIGN(T) (__has_trivial_assign(T) && !is_volatile<T>::value)
# define BOOST_HAS_TRIVIAL_ASSIGN(T) (__has_trivial_assign(T) && !is_volatile<T>::value && is_assignable<T&, const T&>::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<T>::value)
# endif
# if __has_feature(has_nothrow_constructor)
# define BOOST_HAS_NOTHROW_CONSTRUCTOR(T) (__has_nothrow_constructor(T) && is_default_constructible<T>::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<T, T&&>::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<T&, T&&>::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<T>::value)
# define BOOST_HAS_TRIVIAL_COPY(T) ((__has_trivial_copy(T) BOOST_INTEL_TT_OPTS) && !is_reference<T>::value)
# define BOOST_HAS_TRIVIAL_ASSIGN(T) ((__has_trivial_assign(T) BOOST_INTEL_TT_OPTS) && ! ::boost::is_volatile<T>::value && ! ::boost::is_const<T>::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<T>::value && ! ::boost::is_const<T>::value && is_assignable<T&, const T&>::value)
# define BOOST_HAS_TRIVIAL_DESTRUCTOR(T) (__has_trivial_destructor(T) BOOST_INTEL_TT_OPTS && is_destructible<T>::value)
# define BOOST_HAS_NOTHROW_CONSTRUCTOR(T) (__has_nothrow_constructor(T) && is_default_constructible<T>::value BOOST_INTEL_TT_OPTS)
# define BOOST_HAS_NOTHROW_COPY(T) ((__has_nothrow_copy(T) BOOST_INTEL_TT_OPTS) && !is_volatile<T>::value && !is_reference<T>::value && is_constructible<T, const T&>::value)
# define BOOST_HAS_NOTHROW_ASSIGN(T) ((__has_nothrow_assign(T) BOOST_INTEL_TT_OPTS) && !is_volatile<T>::value && !is_const<T>::value && is_assignable<T&, const T&>::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<T&, T&&>::value)
# define BOOST_HAS_TRIVIAL_MOVE_CONSTRUCTOR(T) (__is_trivially_constructible(T, T&&) && is_constructible<T, T&&>::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<T>::value)
# define BOOST_HAS_TRIVIAL_COPY(T) (__oracle_has_trivial_copy(T) && !is_reference<T>::value)
# define BOOST_HAS_TRIVIAL_ASSIGN(T) ((__oracle_has_trivial_assign(T) || __oracle_is_trivial(T)) && ! ::boost::is_volatile<T>::value && ! ::boost::is_const<T>::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<T>::value && ! ::boost::is_const<T>::value && is_assignable<T&, const T&>::value)
# define BOOST_HAS_TRIVIAL_DESTRUCTOR(T) (__oracle_has_trivial_destructor(T) && is_destructible<T>::value)
# define BOOST_HAS_NOTHROW_CONSTRUCTOR(T) ((__oracle_has_nothrow_constructor(T) || __oracle_has_trivial_constructor(T) || __oracle_is_trivial(T)) && is_default_constructible<T>::value)
# define BOOST_HAS_NOTHROW_COPY(T) ((__oracle_has_nothrow_copy(T) || __oracle_has_trivial_copy(T) || __oracle_is_trivial(T)) && !is_volatile<T>::value && !is_reference<T>::value)
# define BOOST_HAS_NOTHROW_ASSIGN(T) ((__oracle_has_nothrow_assign(T) || __oracle_has_trivial_assign(T) || __oracle_is_trivial(T)) && !is_volatile<T>::value && !is_const<T>::value)

View File

@ -43,12 +43,13 @@ namespace boost{
#else
#include <boost/type_traits/has_trivial_constructor.hpp>
#include <boost/type_traits/is_pod.hpp>
namespace boost{
// We don't know how to implement this:
template <class T> struct is_default_constructible : public has_trivial_constructor<T>{};
// 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 <class T> struct is_default_constructible : public is_pod<T>{};
template <> struct is_default_constructible<void> : public integral_constant<bool, false>{};
template <> struct is_default_constructible<void const> : public integral_constant<bool, false>{};
template <> struct is_default_constructible<void volatile> : public integral_constant<bool, false>{};

View File

@ -12,6 +12,23 @@
# include <boost/type_traits/has_trivial_assign.hpp>
#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<bool>::value, true);
@ -180,9 +197,10 @@ BOOST_CHECK_INTEGRAL_CONSTANT(::tt::has_trivial_assign<int&>::value, false);
BOOST_CHECK_INTEGRAL_CONSTANT(::tt::has_trivial_assign<int&&>::value, false);
#endif
BOOST_CHECK_INTEGRAL_CONSTANT(::tt::has_trivial_assign<const int&>::value, false);
BOOST_CHECK_INTEGRAL_CONSTANT(::tt::has_trivial_assign<int[2]>::value, true);
BOOST_CHECK_INTEGRAL_CONSTANT(::tt::has_trivial_assign<int[3][2]>::value, true);
BOOST_CHECK_INTEGRAL_CONSTANT(::tt::has_trivial_assign<int[2][4][5][6][3]>::value, true);
// Arrays can not be explicitly assigned:
BOOST_CHECK_INTEGRAL_CONSTANT(::tt::has_trivial_assign<int[2]>::value, false);
BOOST_CHECK_INTEGRAL_CONSTANT(::tt::has_trivial_assign<int[3][2]>::value, false);
BOOST_CHECK_INTEGRAL_CONSTANT(::tt::has_trivial_assign<int[2][4][5][6][3]>::value, false);
BOOST_CHECK_INTEGRAL_CONSTANT(::tt::has_trivial_assign<UDT>::value, false);
BOOST_CHECK_INTEGRAL_CONSTANT(::tt::has_trivial_assign<empty_UDT>::value, false);
BOOST_CHECK_INTEGRAL_CONSTANT(::tt::has_trivial_assign<void>::value, false);
@ -203,6 +221,11 @@ BOOST_CHECK_SOFT_INTEGRAL_CONSTANT(::tt::has_trivial_assign<wrap<trivial_except_
BOOST_CHECK_INTEGRAL_CONSTANT(::tt::has_trivial_assign<test_abc1>::value, false);
#ifndef BOOST_NO_CXX11_DELETED_FUNCTIONS
BOOST_CHECK_INTEGRAL_CONSTANT(::tt::has_trivial_assign<non_assignable2>::value, false);
#endif
BOOST_CHECK_INTEGRAL_CONSTANT(::tt::has_trivial_assign<non_assignable>::value, false);
TT_TEST_END

View File

@ -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<int[3][2]>::value, t
BOOST_CHECK_INTEGRAL_CONSTANT(::tt::has_trivial_constructor<int[2][4][5][6][3]>::value, true);
BOOST_CHECK_INTEGRAL_CONSTANT(::tt::has_trivial_constructor<UDT>::value, false);
BOOST_CHECK_INTEGRAL_CONSTANT(::tt::has_trivial_constructor<empty_UDT>::value, false);
BOOST_CHECK_INTEGRAL_CONSTANT(::tt::has_trivial_constructor<void>::value, true);
// Can't construct type void:
BOOST_CHECK_INTEGRAL_CONSTANT(::tt::has_trivial_constructor<void>::value, false);
// cases we would like to succeed but can't implement in the language:
BOOST_CHECK_SOFT_INTEGRAL_CONSTANT(::tt::has_trivial_constructor<empty_POD_UDT>::value, true, false);
BOOST_CHECK_SOFT_INTEGRAL_CONSTANT(::tt::has_trivial_constructor<POD_UDT>::value, true, false);
@ -187,6 +204,11 @@ BOOST_CHECK_SOFT_INTEGRAL_CONSTANT(::tt::has_trivial_constructor<wrap<trivial_ex
BOOST_CHECK_INTEGRAL_CONSTANT(::tt::has_trivial_constructor<test_abc1>::value, false);
BOOST_CHECK_INTEGRAL_CONSTANT(::tt::has_trivial_constructor<bug11324_derived>::value, false);
BOOST_CHECK_INTEGRAL_CONSTANT(::tt::has_trivial_constructor<private_construct>::value, false);
#ifndef BOOST_NO_CXX11_DELETED_FUNCTIONS
BOOST_CHECK_INTEGRAL_CONSTANT(::tt::has_trivial_constructor<deleted_construct>::value, false);
#endif
TT_TEST_END

View File

@ -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<bool>::value, true);
@ -220,6 +227,7 @@ BOOST_CHECK_INTEGRAL_CONSTANT(::tt::has_trivial_copy<test_abc1>::value, false);
#ifndef BOOST_NO_CXX11_DELETED_FUNCTIONS
BOOST_CHECK_INTEGRAL_CONSTANT(::tt::has_trivial_copy<bug_10389>::value, false);
#endif
BOOST_CHECK_INTEGRAL_CONSTANT(::tt::has_trivial_copy<private_copy>::value, false);
TT_TEST_END

View File

@ -12,6 +12,23 @@
# include <boost/type_traits/has_trivial_destructor.hpp>
#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<bool>::value, true);
@ -170,6 +187,11 @@ BOOST_CHECK_SOFT_INTEGRAL_CONSTANT(::tt::has_trivial_destructor<wrap<trivial_exc
BOOST_CHECK_SOFT_INTEGRAL_CONSTANT(::tt::has_trivial_destructor<wrap<trivial_except_construct> >::value, true, false);
BOOST_CHECK_SOFT_INTEGRAL_CONSTANT(::tt::has_trivial_destructor<wrap<trivial_except_assign> >::value, true, false);
BOOST_CHECK_INTEGRAL_CONSTANT(::tt::has_trivial_destructor<private_destruct>::value, false);
#ifndef BOOST_NO_CXX11_DELETED_FUNCTIONS
BOOST_CHECK_INTEGRAL_CONSTANT(::tt::has_trivial_destructor<deleted_destruct>::value, false);
#endif
TT_TEST_END

View File

@ -13,6 +13,38 @@
# include <boost/type_traits/has_trivial_move_assign.hpp>
#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<bool>::value, true);
@ -204,6 +236,11 @@ BOOST_CHECK_SOFT_INTEGRAL_CONSTANT(::tt::has_trivial_move_assign<wrap<trivial_ex
BOOST_CHECK_INTEGRAL_CONSTANT(::tt::has_trivial_move_assign<test_abc1>::value, false);
#ifndef BOOST_NO_CXX11_DELETED_FUNCTIONS
BOOST_CHECK_SOFT_INTEGRAL_CONSTANT(::tt::has_trivial_move_assign<non_copyable_movable>::value, true, false);
BOOST_CHECK_INTEGRAL_CONSTANT(::tt::has_trivial_move_assign<copyable_non_moveable>::value, false);
#endif
TT_TEST_END

View File

@ -13,6 +13,39 @@
# include <boost/type_traits/has_trivial_move_constructor.hpp>
#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<bool>::value, true);
@ -204,6 +237,11 @@ BOOST_CHECK_SOFT_INTEGRAL_CONSTANT(::tt::has_trivial_move_constructor<wrap<trivi
BOOST_CHECK_INTEGRAL_CONSTANT(::tt::has_trivial_move_constructor<test_abc1>::value, false);
#ifndef BOOST_NO_CXX11_DELETED_FUNCTIONS
BOOST_CHECK_SOFT_INTEGRAL_CONSTANT(::tt::has_trivial_move_constructor<non_copyable_movable>::value, true, false);
BOOST_CHECK_INTEGRAL_CONSTANT(::tt::has_trivial_move_constructor<copyable_non_moveable>::value, false);
#endif
TT_TEST_END