diff --git a/include/boost/container/detail/utilities.hpp b/include/boost/container/detail/utilities.hpp index 077b298..d5c6b99 100644 --- a/include/boost/container/detail/utilities.hpp +++ b/include/boost/container/detail/utilities.hpp @@ -21,7 +21,13 @@ #include #include #include +#include +#include +#include #include +#include +#include +#include #include #include #include @@ -31,8 +37,6 @@ #include #include #include -#include -#include #include #include #include @@ -387,6 +391,33 @@ I memmove_n_source_dest(I f, typename std::iterator_traits::difference_type n return f; } +template +struct is_memzero_initializable +{ + typedef typename ::std::iterator_traits::value_type value_type; + static const bool value = are_elements_contiguous::value && + ( ::boost::is_integral::value + #if BOOST_CONTAINER_MEMZEROED_POINTER_IS_NULL + || ::boost::is_pointer::value + #endif + #if BOOST_CONTAINER_MEMZEROED_FLOATING_POINT_IS_ZERO + || ::boost::is_floating_point::value + #endif + #if BOOST_CONTAINER_MEMZEROED_FLOATING_POINT_IS_ZERO && BOOST_CONTAINER_MEMZEROED_POINTER_IS_NULL + || ::boost::is_pod::value + #endif + ); +}; + +template +struct enable_if_memzero_initializable + : public enable_if_c::value, R> +{}; + +template +struct disable_if_memzero_initializable + : public enable_if_c::value, R> +{}; } //namespace container_detail { @@ -678,7 +709,8 @@ inline typename container_detail::enable_if_memtransfer_copy_constructible // F models ForwardIterator -inline F uninitialized_value_init_alloc_n(A &a, typename allocator_traits::difference_type n, F r) +inline typename container_detail::disable_if_memzero_initializable::type + uninitialized_value_init_alloc_n(A &a, typename allocator_traits::difference_type n, F r) { F back = r; BOOST_TRY{ @@ -697,6 +729,18 @@ inline F uninitialized_value_init_alloc_n(A &a, typename allocator_traits::di return r; } +template + // F models ForwardIterator +inline typename container_detail::enable_if_memzero_initializable::type + uninitialized_value_init_alloc_n(A &, typename allocator_traits::difference_type n, F r) +{ + typedef typename std::iterator_traits::value_type value_type; + ::memset((void*)container_detail::addressof(*r), 0, sizeof(value_type)*n); + std::advance(r, n); + return r; +} + ////////////////////////////////////////////////////////////////////////////// // // uninitialized_default_init_alloc_n diff --git a/include/boost/container/detail/workaround.hpp b/include/boost/container/detail/workaround.hpp index f919aa5..a12e820 100644 --- a/include/boost/container/detail/workaround.hpp +++ b/include/boost/container/detail/workaround.hpp @@ -45,6 +45,19 @@ #define BOOST_CONTAINER_IMPDEF(TYPE) TYPE #define BOOST_CONTAINER_SEEDOC(TYPE) TYPE +//Macros for memset optimization. In most platforms +//memsetting pointers and floatings is safe and faster. +// +//If your platform does not offer these guarantees +//define these to value zero. +#ifndef BOOST_CONTAINER_MEMZEROED_FLOATING_POINT_IS_ZERO +#define BOOST_CONTAINER_MEMZEROED_FLOATING_POINT_IS_ZERO 1 +#endif + +#ifndef BOOST_CONTAINER_MEMZEROED_POINTER_IS_NULL +#define BOOST_CONTAINER_MEMZEROED_POINTER_IS_NULL 1 +#endif + #include #endif //#ifndef BOOST_CONTAINER_DETAIL_WORKAROUND_HPP