From e03a8732a676ca7ff8b2e03aa9ad50c30a21cb81 Mon Sep 17 00:00:00 2001 From: Daniel James Date: Mon, 17 Oct 2016 07:54:06 +0100 Subject: [PATCH] Use static_cast for allocator_traits::construct std::allocator::construct uses a C-style cast to void pointer, so it can accept const pointers, but allocator_traits::construct uses a static_cast by default, so const pointers don't work. This means the implementation needs to cast away const when constructing members of a std::pair. This wouldn't happen if piecewise construction was used, as the members could be constructed normally. --- include/boost/unordered/detail/allocate.hpp | 34 ++++++++++++++------- 1 file changed, 23 insertions(+), 11 deletions(-) diff --git a/include/boost/unordered/detail/allocate.hpp b/include/boost/unordered/detail/allocate.hpp index 7a330ca2..3ff26151 100644 --- a/include/boost/unordered/detail/allocate.hpp +++ b/include/boost/unordered/detail/allocate.hpp @@ -703,7 +703,7 @@ namespace boost { namespace unordered { namespace detail { ::value>::type construct(Alloc&, T* p, BOOST_FWD_REF(Args)... x) { - new ((void*) p) T(boost::forward(x)...); + new (static_cast(p)) T(boost::forward(x)...); } template @@ -737,7 +737,7 @@ namespace boost { namespace unordered { namespace detail { boost::unordered::detail::has_construct::value>::type construct(Alloc&, T* p, T const& x) { - new ((void*) p) T(x); + new (static_cast(p)) T(x); } template @@ -779,7 +779,7 @@ namespace boost { namespace unordered { namespace detail { boost::is_same::value, void*>::type = 0) { - new ((void*) p) T(x); + new (static_cast(p)) T(x); } template @@ -1331,6 +1331,14 @@ namespace boost { namespace unordered { namespace detail { namespace func { return a.release(); } + // This is a bit nasty, when constructing the individual members + // of a std::pair, need to cast away 'const'. For modern compilers, + // should be able to use std::piecewise_construct instead. + template T* const_cast_pointer(T* x) { return x; } + template T* const_cast_pointer(T const* x) { + return const_cast(x); + } + // TODO: When possible, it might be better to use std::pair's // constructor for std::piece_construct with std::tuple. template @@ -1339,11 +1347,13 @@ namespace boost { namespace unordered { namespace detail { namespace func { { node_constructor a(alloc); a.create_node(); - boost::unordered::detail::func::call_construct( - alloc, boost::addressof(a.node_->value_ptr()->first), + boost::unordered::detail::func::call_construct(alloc, + boost::unordered::detail::func::const_cast_pointer( + boost::addressof(a.node_->value_ptr()->first)), boost::forward(k)); - boost::unordered::detail::func::call_construct( - alloc, boost::addressof(a.node_->value_ptr()->second)); + boost::unordered::detail::func::call_construct(alloc, + boost::unordered::detail::func::const_cast_pointer( + boost::addressof(a.node_->value_ptr()->second))); return a.release(); } @@ -1353,11 +1363,13 @@ namespace boost { namespace unordered { namespace detail { namespace func { { node_constructor a(alloc); a.create_node(); - boost::unordered::detail::func::call_construct( - alloc, boost::addressof(a.node_->value_ptr()->first), + boost::unordered::detail::func::call_construct(alloc, + boost::unordered::detail::func::const_cast_pointer( + boost::addressof(a.node_->value_ptr()->first)), boost::forward(k)); - boost::unordered::detail::func::call_construct( - alloc, boost::addressof(a.node_->value_ptr()->second), + boost::unordered::detail::func::call_construct(alloc, + boost::unordered::detail::func::const_cast_pointer( + boost::addressof(a.node_->value_ptr()->second)), boost::forward(m)); return a.release(); }