diff --git a/include/boost/move/detail/meta_utils.hpp b/include/boost/move/detail/meta_utils.hpp index 1104a28..70fbc05 100644 --- a/include/boost/move/detail/meta_utils.hpp +++ b/include/boost/move/detail/meta_utils.hpp @@ -116,39 +116,13 @@ struct add_const ////////////////////////////////////// template struct add_lvalue_reference -{ - typedef T& type; -}; +{ typedef T& type; }; -template -struct add_lvalue_reference -{ - typedef T& type; -}; - -template<> -struct add_lvalue_reference -{ - typedef void type; -}; - -template<> -struct add_lvalue_reference -{ - typedef const void type; -}; - -template<> -struct add_lvalue_reference -{ - typedef volatile void type; -}; - -template<> -struct add_lvalue_reference -{ - typedef const volatile void type; -}; +template struct add_lvalue_reference { typedef T& type; }; +template<> struct add_lvalue_reference { typedef void type; }; +template<> struct add_lvalue_reference { typedef const void type; }; +template<> struct add_lvalue_reference { typedef volatile void type; }; +template<> struct add_lvalue_reference{ typedef const volatile void type; }; template struct add_const_lvalue_reference diff --git a/include/boost/move/detail/type_traits.hpp b/include/boost/move/detail/type_traits.hpp index 0ee31aa..cf91acb 100644 --- a/include/boost/move/detail/type_traits.hpp +++ b/include/boost/move/detail/type_traits.hpp @@ -70,6 +70,7 @@ // user defined specializations as well as compiler intrinsics as // and when they become available: # include +# define BOOST_MOVE_IS_UNION(T) BOOST_STD_EXTENSION_NAMESPACE::is_union::value # define BOOST_MOVE_IS_POD(T) BOOST_STD_EXTENSION_NAMESPACE::is_POD::value # define BOOST_MOVE_HAS_TRIVIAL_CONSTRUCTOR(T) BOOST_STD_EXTENSION_NAMESPACE::has_trivial_default_ctor::value # define BOOST_MOVE_HAS_TRIVIAL_COPY(T) BOOST_STD_EXTENSION_NAMESPACE::has_trivial_copy_ctor::value @@ -79,7 +80,9 @@ #if (defined(BOOST_MSVC) && defined(BOOST_MSVC_FULL_VER) && (BOOST_MSVC_FULL_VER >=140050215))\ || (defined(BOOST_INTEL) && defined(_MSC_VER) && (_MSC_VER >= 1500)) +# define BOOST_MOVE_IS_UNION(T) __is_union(T) # define BOOST_MOVE_IS_POD(T) (__is_pod(T) && __has_trivial_constructor(T)) +# define BOOST_MOVE_IS_EMPTY(T) __is_empty(T) # define BOOST_MOVE_HAS_TRIVIAL_CONSTRUCTOR(T) __has_trivial_constructor(T) # define BOOST_MOVE_HAS_TRIVIAL_COPY(T) (__has_trivial_copy(T)|| ::boost::move_detail::is_pod::value) # define BOOST_MOVE_HAS_TRIVIAL_ASSIGN(T) (__has_trivial_assign(T) || ::boost::move_detail::is_pod::value) @@ -97,14 +100,22 @@ #if defined(BOOST_CLANG) && defined(__has_feature) +# if __has_feature(is_union) +# define BOOST_MOVE_IS_UNION(T) __is_union(T) +# endif # if (!defined(__GLIBCXX__) || (__GLIBCXX__ >= 20080306 && __GLIBCXX__ != 20080519)) && __has_feature(is_pod) # define BOOST_MOVE_IS_POD(T) __is_pod(T) # endif +# if (!defined(__GLIBCXX__) || (__GLIBCXX__ >= 20080306 && __GLIBCXX__ != 20080519)) && __has_feature(is_empty) +# define BOOST_MOVE_IS_EMPTY(T) __is_empty(T) +# endif # if __has_feature(has_trivial_constructor) # define BOOST_MOVE_HAS_TRIVIAL_CONSTRUCTOR(T) __has_trivial_constructor(T) # endif # if __has_feature(has_trivial_copy) -# define BOOST_MOVE_HAS_TRIVIAL_COPY(T) (__has_trivial_copy(T)) +# //There are problems with deleted copy constructors detected as trivially copyable. +# //http://stackoverflow.com/questions/12754886/has-trivial-copy-behaves-differently-in-clang-and-gcc-whos-right +# define BOOST_MOVE_HAS_TRIVIAL_COPY(T) (__has_trivial_copy(T) && ::boost::move_detail::is_copy_constructible::value) # endif # if __has_feature(has_trivial_assign) # define BOOST_MOVE_HAS_TRIVIAL_ASSIGN(T) (__has_trivial_assign(T) ) @@ -141,7 +152,9 @@ # define BOOST_MOVE_INTEL_TT_OPTS #endif +# define BOOST_MOVE_IS_UNION(T) __is_union(T) # define BOOST_MOVE_IS_POD(T) __is_pod(T) +# define BOOST_MOVE_IS_EMPTY(T) __is_empty(T) # define BOOST_MOVE_HAS_TRIVIAL_CONSTRUCTOR(T) ((__has_trivial_constructor(T) BOOST_MOVE_INTEL_TT_OPTS)) # define BOOST_MOVE_HAS_TRIVIAL_COPY(T) ((__has_trivial_copy(T) BOOST_MOVE_INTEL_TT_OPTS)) # define BOOST_MOVE_HAS_TRIVIAL_ASSIGN(T) ((__has_trivial_assign(T) BOOST_MOVE_INTEL_TT_OPTS) ) @@ -161,7 +174,9 @@ #if defined(__ghs__) && (__GHS_VERSION_NUMBER >= 600) +# define BOOST_MOVE_IS_UNION(T) __is_union(T) # define BOOST_MOVE_IS_POD(T) __is_pod(T) +# define BOOST_MOVE_IS_EMPTY(T) __is_empty(T) # define BOOST_MOVE_HAS_TRIVIAL_CONSTRUCTOR(T) __has_trivial_constructor(T) # define BOOST_MOVE_HAS_TRIVIAL_COPY(T) (__has_trivial_copy(T)) # define BOOST_MOVE_HAS_TRIVIAL_ASSIGN(T) (__has_trivial_assign(T)) @@ -175,7 +190,9 @@ #endif # if defined(__CODEGEARC__) +# define BOOST_MOVE_IS_UNION(T) __is_union(T) # define BOOST_MOVE_IS_POD(T) __is_pod(T) +# define BOOST_MOVE_IS_EMPTY(T) __is_empty(T) # define BOOST_MOVE_HAS_TRIVIAL_CONSTRUCTOR(T) (__has_trivial_default_constructor(T)) # define BOOST_MOVE_HAS_TRIVIAL_COPY(T) (__has_trivial_copy_constructor(T)) # define BOOST_MOVE_HAS_TRIVIAL_ASSIGN(T) (__has_trivial_assign(T)) @@ -190,6 +207,13 @@ #endif //Fallback definitions + +#ifdef BOOST_MOVE_IS_UNION + #define BOOST_MOVE_IS_UNION_IMPL(T) BOOST_MOVE_IS_UNION(T) +#else + #define BOOST_MOVE_IS_UNION_IMPL(T) false +#endif + #ifdef BOOST_MOVE_IS_POD #define BOOST_MOVE_IS_POD_IMPL(T) BOOST_MOVE_IS_POD(T) #else @@ -197,6 +221,12 @@ (::boost::move_detail::is_scalar::value || ::boost::move_detail::is_void::value) #endif +#ifdef BOOST_MOVE_IS_EMPTY + #define BOOST_MOVE_IS_EMPTY_IMPL(T) BOOST_MOVE_IS_EMPTY(T) +#else + #define BOOST_MOVE_IS_EMPTY_IMPL(T) ::boost::move_detail::is_empty_nonintrinsic::value +#endif + #ifdef BOOST_MOVE_HAS_TRIVIAL_COPY #define BOOST_MOVE_IS_TRIVIALLY_COPY_CONSTRUCTIBLE(T) BOOST_MOVE_HAS_TRIVIAL_COPY(T) #else @@ -419,6 +449,21 @@ struct is_integral : public is_integral_cv::type> {}; +////////////////////////////////////// +// remove_all_extents +////////////////////////////////////// +template +struct remove_all_extents +{ typedef T type;}; + +template +struct remove_all_extents +{ typedef typename remove_all_extents::type type; }; + +template +struct remove_all_extents +{ typedef typename remove_all_extents::type type;}; + ////////////////////////// // is_scalar ////////////////////////// @@ -529,6 +574,57 @@ struct is_function : is_function_impl {}; +////////////////////////////////////// +// is_union +////////////////////////////////////// +template +struct is_union_noextents_cv +{ static const bool value = BOOST_MOVE_IS_UNION_IMPL(T); }; + +template +struct is_union + : is_union_noextents_cv::type>::type> +{}; + +////////////////////////////////////// +// is_class +////////////////////////////////////// +template +struct is_class +{ + static const bool value = is_class_or_union::value && ! is_union::value; +}; + + +////////////////////////////////////// +// is_arithmetic +////////////////////////////////////// +template +struct is_arithmetic +{ + static const bool value = is_floating_point::value || + is_integral::value; +}; + +////////////////////////////////////// +// is_member_function_pointer +////////////////////////////////////// +template +struct is_member_function_pointer_cv +{ + static const bool value = false; +}; + +template +struct is_member_function_pointer_cv + : is_function +{}; + +template +struct is_member_function_pointer + : is_member_function_pointer_cv::type> +{}; + ////////////////////////////////////// // is_enum ////////////////////////////////////// @@ -537,15 +633,14 @@ struct is_function template struct is_enum_nonintrinsic { - static const bool value = !is_void::value && - !is_floating_point::value && - !is_integral::value && + static const bool value = !is_arithmetic::value && + !is_reference::value && + !is_class_or_union::value && + !is_array::value && + !is_void::value && !is_nullptr_t::value && !is_member_pointer::value && !is_pointer::value && - !is_array::value && - !is_class_or_union::value && - !is_reference::value && !is_function::value; }; #endif @@ -554,21 +649,6 @@ template struct is_enum { static const bool value = BOOST_MOVE_IS_ENUM_IMPL(T); }; -////////////////////////////////////// -// remove_all_extents -////////////////////////////////////// -template -struct remove_all_extents -{ typedef T type;}; - -template -struct remove_all_extents -{ typedef typename remove_all_extents::type type; }; - -template -struct remove_all_extents -{ typedef typename remove_all_extents::type type;}; - ////////////////////////////////////// // is_pod ////////////////////////////////////// @@ -581,6 +661,41 @@ struct is_pod : is_pod_noextents_cv::type>::type> {}; +////////////////////////////////////// +// is_empty +////////////////////////////////////// +#if !defined(BOOST_MOVE_IS_EMPTY) + +template +struct empty_helper_t1 : public T +{ + empty_helper_t1(); // hh compiler bug workaround + int i[256]; + private: + + empty_helper_t1(const empty_helper_t1&); + empty_helper_t1& operator=(const empty_helper_t1&); +}; + +struct empty_helper_t2 { int i[256]; }; + +template ::value > +struct is_empty_nonintrinsic +{ + static const bool value = false; +}; + +template +struct is_empty_nonintrinsic +{ + static const bool value = sizeof(empty_helper_t1) == sizeof(empty_helper_t2); +}; +#endif + +template +struct is_empty +{ static const bool value = BOOST_MOVE_IS_EMPTY_IMPL(T); }; + ////////////////////////////////////// // is_copy_constructible ////////////////////////////////////// @@ -695,6 +810,15 @@ template struct is_nothrow_move_assignable { static const bool value = BOOST_MOVE_IS_NOTHROW_MOVE_ASSIGNABLE(T); }; +////////////////////////////////////// +// is_nothrow_swappable +////////////////////////////////////// +template +struct is_nothrow_swappable +{ + static const bool value = is_empty::value || is_pod::value; +}; + ////////////////////////////////////// // alignment_of //////////////////////////////////////