From 69598a3d3ffe330bec11cb9174517f949d5e9059 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ion=20Gazta=C3=B1aga?= Date: Sun, 26 Apr 2015 23:29:27 +0200 Subject: [PATCH] - Reworked some traits to refactor code - is_trivially_copy_xxxxable updated to add is_pod - Updated is_pod adding scalar and void as some compilers' __is_pod intrinsic doesn't work with scalars - Added test for type_traits. Only a few tested, more to come. --- include/boost/move/detail/type_traits.hpp | 58 ++++++---- proj/vc7ide/Move.sln | 8 ++ proj/vc7ide/type_traits.vcproj | 135 ++++++++++++++++++++++ test/type_traits.cpp | 98 ++++++++++++++++ test/unique_ptr_types.cpp | 41 ++++--- 5 files changed, 299 insertions(+), 41 deletions(-) create mode 100644 proj/vc7ide/type_traits.vcproj create mode 100644 test/type_traits.cpp diff --git a/include/boost/move/detail/type_traits.hpp b/include/boost/move/detail/type_traits.hpp index ed02361..8e67755 100644 --- a/include/boost/move/detail/type_traits.hpp +++ b/include/boost/move/detail/type_traits.hpp @@ -219,7 +219,10 @@ #endif #ifdef BOOST_MOVE_IS_POD - #define BOOST_MOVE_IS_POD_IMPL(T) BOOST_MOVE_IS_POD(T) + //in some compilers the intrinsic is limited to class types so add scalar and void + #define BOOST_MOVE_IS_POD_IMPL(T) (::boost::move_detail::is_scalar::value ||\ + ::boost::move_detail::is_void::value ||\ + BOOST_MOVE_IS_POD(T)) #else #define BOOST_MOVE_IS_POD_IMPL(T) \ (::boost::move_detail::is_scalar::value || ::boost::move_detail::is_void::value) @@ -702,16 +705,31 @@ template struct is_empty { static const bool value = BOOST_MOVE_IS_EMPTY_IMPL(T); }; + +template +struct has_boost_move_no_copy_constructor_or_assign_type +{ + template + static yes_type test(typename U::boost_move_no_copy_constructor_or_assign*); + + template + static no_type test(...); + + static const bool value = sizeof(test(0)) == sizeof(yes_type); +}; + ////////////////////////////////////// // is_copy_constructible ////////////////////////////////////// +#if !defined(BOOST_NO_CXX11_DELETED_FUNCTIONS) && !defined(BOOST_NO_CXX11_DECLTYPE) \ + && !defined(BOOST_INTEL_CXX_VERSION) && \ + !(defined(BOOST_MSVC) && _MSC_VER == 1800) +#define BOOST_MOVE_TT_CXX11_IS_COPY_CONSTRUCTIBLE +#endif + template struct is_copy_constructible { - typedef char yes_type; - struct no_type { char dummy[2]; }; - template static typename add_reference::type source(); - // Intel compiler has problems with SFINAE for copy constructors and deleted functions: // // error: function *function_name* cannot be referenced -- it is a deleted function @@ -719,8 +737,8 @@ struct is_copy_constructible // ^ // MSVC 12.0 (Visual 2013) has problems when the copy constructor has been deleted. See: // https://connect.microsoft.com/VisualStudio/feedback/details/800328/std-is-copy-constructible-is-broken - #if !defined(BOOST_NO_CXX11_DELETED_FUNCTIONS) && !defined(BOOST_INTEL_CXX_VERSION) &&\ - !(defined(BOOST_MSVC) && _MSC_VER == 1800) + #if defined(BOOST_MOVE_TT_CXX11_IS_COPY_CONSTRUCTIBLE) + template static typename add_reference::type source(); static no_type test(...); #ifdef BOOST_NO_CXX11_DECLTYPE template @@ -729,15 +747,13 @@ struct is_copy_constructible template static yes_type test(U&, decltype(U(source()))* = 0); #endif + static const bool value = sizeof(test(source())) == sizeof(yes_type); #else - template - static no_type test(U&, typename U::boost_move_no_copy_constructor_or_assign* = 0); - static yes_type test(...); + static const bool value = !has_boost_move_no_copy_constructor_or_assign_type::value; #endif - - static const bool value = sizeof(test(source())) == sizeof(yes_type); }; + ////////////////////////////////////// // is_copy_assignable ////////////////////////////////////// @@ -768,13 +784,7 @@ struct is_copy_assignable static const bool value = sizeof(test(0)) == sizeof(yes_type); #else - static typename add_reference::type produce(); - - template - static no_type test(T1&, typename T1::boost_move_no_copy_constructor_or_assign* = 0); - static yes_type test(...); - - static const bool value = sizeof(test(produce())) == sizeof(yes_type); + static const bool value = !has_boost_move_no_copy_constructor_or_assign_type::value; #endif }; @@ -800,8 +810,9 @@ struct is_trivially_copy_constructible { //In several compilers BOOST_MOVE_IS_TRIVIALLY_COPY_CONSTRUCTIBLE return true even with //deleted copy constructors so make sure the type is copy constructible. - static const bool value = ::boost::move_detail::is_copy_constructible::value && - BOOST_MOVE_IS_TRIVIALLY_COPY_CONSTRUCTIBLE(T); + static const bool value = ::boost::move_detail::is_pod::value || + ( ::boost::move_detail::is_copy_constructible::value && + BOOST_MOVE_IS_TRIVIALLY_COPY_CONSTRUCTIBLE(T) ); }; ////////////////////////////////////// @@ -819,8 +830,9 @@ struct is_trivially_copy_assignable { //In several compilers BOOST_MOVE_IS_TRIVIALLY_COPY_CONSTRUCTIBLE return true even with //deleted copy constructors so make sure the type is copy constructible. - static const bool value = ::boost::move_detail::is_copy_assignable::value && - BOOST_MOVE_IS_TRIVIALLY_COPY_ASSIGNABLE(T); + static const bool value = ::boost::move_detail::is_pod::value || + ( ::boost::move_detail::is_copy_assignable::value && + BOOST_MOVE_IS_TRIVIALLY_COPY_ASSIGNABLE(T) ); }; ////////////////////////////////////// diff --git a/proj/vc7ide/Move.sln b/proj/vc7ide/Move.sln index 4b230a8..06e5cc9 100644 --- a/proj/vc7ide/Move.sln +++ b/proj/vc7ide/Move.sln @@ -107,6 +107,10 @@ Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "adl_move_swap", "adl_move_s ProjectSection(ProjectDependencies) = postProject EndProjectSection EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "type_traits", "type_traits.vcproj", "{D7C28A23-8621-FE05-BF87-3C7B6176BD02}" + ProjectSection(ProjectDependencies) = postProject + EndProjectSection +EndProject Global GlobalSection(SolutionConfiguration) = preSolution Debug = Debug @@ -223,6 +227,10 @@ Global {CD2617A8-79EB-6172-2CE4-26617AA3AC93}.Debug.Build.0 = Debug|Win32 {CD2617A8-79EB-6172-2CE4-26617AA3AC93}.Release.ActiveCfg = Release|Win32 {CD2617A8-79EB-6172-2CE4-26617AA3AC93}.Release.Build.0 = Release|Win32 + {D7C28A23-8621-FE05-BF87-3C7B6176BD02}.Debug.ActiveCfg = Debug|Win32 + {D7C28A23-8621-FE05-BF87-3C7B6176BD02}.Debug.Build.0 = Debug|Win32 + {D7C28A23-8621-FE05-BF87-3C7B6176BD02}.Release.ActiveCfg = Release|Win32 + {D7C28A23-8621-FE05-BF87-3C7B6176BD02}.Release.Build.0 = Release|Win32 EndGlobalSection GlobalSection(SolutionItems) = postSolution ..\..\..\..\boost\move\adl_move_swap.hpp = ..\..\..\..\boost\move\adl_move_swap.hpp diff --git a/proj/vc7ide/type_traits.vcproj b/proj/vc7ide/type_traits.vcproj new file mode 100644 index 0000000..daa696a --- /dev/null +++ b/proj/vc7ide/type_traits.vcproj @@ -0,0 +1,135 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/test/type_traits.cpp b/test/type_traits.cpp new file mode 100644 index 0000000..3625777 --- /dev/null +++ b/test/type_traits.cpp @@ -0,0 +1,98 @@ +////////////////////////////////////////////////////////////////////////////// +// +// (C) Copyright Ion Gaztanaga 2015-2015. +// +// 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) +// +// See http://www.boost.org/libs/move for documentation. +// +////////////////////////////////////////////////////////////////////////////// +#include +#include +#include +#include + +// +// pod_struct +// +#if defined(BOOST_MOVE_IS_POD) +struct pod_struct +{ + int i; + float f; +}; +#endif + +// +// deleted_copy_and_assign_type +// +#if !defined(BOOST_NO_CXX11_DELETED_FUNCTIONS) + +struct deleted_copy_and_assign_type +{ + deleted_copy_and_assign_type(const deleted_copy_and_assign_type&) = delete; + deleted_copy_and_assign_type & operator=(const deleted_copy_and_assign_type&) = delete; +}; + +#endif //defined(BOOST_NO_CXX11_DELETED_FUNCTIONS) + +// +// boost_move_type +// +class boost_move_type +{ + BOOST_MOVABLE_BUT_NOT_COPYABLE(boost_move_type) + public: + boost_move_type(BOOST_RV_REF(boost_move_type)){} + boost_move_type & operator=(BOOST_RV_REF(boost_move_type)){ return *this; } +}; + +namespace is_pod_test +{ + +void test() +{ + BOOST_STATIC_ASSERT((boost::move_detail::is_pod::value)); + #if defined(BOOST_MOVE_IS_POD) + BOOST_STATIC_ASSERT((boost::move_detail::is_pod::value)); + #endif +} + +} //namespace is_pod_test + +namespace trivially_memcopyable_test { + +void test() +{ + #if !defined(BOOST_NO_CXX11_DELETED_FUNCTIONS) + BOOST_STATIC_ASSERT(!(boost::move_detail::is_trivially_copy_constructible::value)); + BOOST_STATIC_ASSERT(!(boost::move_detail::is_trivially_copy_assignable::value)); + #endif //#if !defined(BOOST_NO_CXX11_DELETED_FUNCTIONS) + //boost_move_type + BOOST_STATIC_ASSERT(!(boost::move_detail::is_trivially_copy_constructible::value)); + BOOST_STATIC_ASSERT(!(boost::move_detail::is_trivially_copy_assignable::value)); + BOOST_STATIC_ASSERT(!(boost::move_detail::is_copy_constructible::value)); + BOOST_STATIC_ASSERT(!(boost::move_detail::is_copy_assignable::value)); + //POD + BOOST_STATIC_ASSERT((boost::move_detail::is_trivially_copy_constructible::value)); + BOOST_STATIC_ASSERT((boost::move_detail::is_trivially_copy_assignable::value)); + BOOST_STATIC_ASSERT((boost::move_detail::is_copy_constructible::value)); + BOOST_STATIC_ASSERT((boost::move_detail::is_copy_assignable::value)); + #if defined(BOOST_MOVE_IS_POD) + BOOST_STATIC_ASSERT((boost::move_detail::is_trivially_copy_constructible::value)); + BOOST_STATIC_ASSERT((boost::move_detail::is_trivially_copy_assignable::value)); + BOOST_STATIC_ASSERT((boost::move_detail::is_copy_constructible::value)); + BOOST_STATIC_ASSERT((boost::move_detail::is_copy_assignable::value)); + #endif +} + +} //namespace trivially_memcopyable_test { + +int main() +{ + trivially_memcopyable_test::test(); + is_pod_test::test(); + boost::report_errors(); +} diff --git a/test/unique_ptr_types.cpp b/test/unique_ptr_types.cpp index a88b46c..799b417 100644 --- a/test/unique_ptr_types.cpp +++ b/test/unique_ptr_types.cpp @@ -149,12 +149,30 @@ void test() } //namespace unique_ptr_element_type { //////////////////////////////// -// main +// unique_ptr_construct_assign_traits //////////////////////////////// -#if __cplusplus >= 201103L -#include -#endif +namespace unique_ptr_construct_assign_traits { + + void test() + { + typedef bml::unique_ptr unique_ptr_t; + //Even if BOOST_MOVE_TT_CXX11_IS_COPY_CONSTRUCTIBLE is not defined + //boost::unique_ptr shall work with boost::movelib traits + BOOST_STATIC_ASSERT(!(boost::move_detail::is_copy_constructible::value)); + //Even if BOOST_MOVE_TT_CXX11_IS_COPY_ASSIGNABLE is not defined + //boost::unique_ptr shall work with boost::movelib traits + BOOST_STATIC_ASSERT(!(boost::move_detail::is_copy_assignable::value)); + //Important traits for containers like boost::vector + BOOST_STATIC_ASSERT(!(boost::move_detail::is_trivially_copy_constructible::value)); + BOOST_STATIC_ASSERT(!(boost::move_detail::is_trivially_copy_assignable::value)); + } + +} //namespace unique_ptr_construct_assign_traits { + +//////////////////////////////// +// main +//////////////////////////////// int main() { @@ -162,23 +180,10 @@ int main() unique_ptr_pointer_type::test(); unique_ptr_deleter_type::test(); unique_ptr_element_type::test(); - - typedef bml::unique_ptr unique_ptr_t; - BOOST_STATIC_ASSERT(!(boost::move_detail::is_copy_constructible::value)); - BOOST_STATIC_ASSERT(!(boost::move_detail::is_copy_assignable::value)); - BOOST_STATIC_ASSERT(!(boost::move_detail::is_trivially_copy_constructible::value)); - BOOST_STATIC_ASSERT(!(boost::move_detail::is_trivially_copy_assignable::value)); - #if __cplusplus >= 201103L - typedef std::unique_ptr std_unique_ptr_t; - BOOST_STATIC_ASSERT(!(boost::move_detail::is_copy_constructible::value)); - BOOST_STATIC_ASSERT(!(boost::move_detail::is_copy_assignable::value)); - BOOST_STATIC_ASSERT(!(boost::move_detail::is_trivially_copy_constructible::value)); - BOOST_STATIC_ASSERT(!(boost::move_detail::is_trivially_copy_assignable::value)); - #endif + unique_ptr_construct_assign_traits::test(); //Test results return boost::report_errors(); - } #include "unique_ptr_test_utils_end.hpp"