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.
This commit is contained in:
Daniel James
2016-10-17 07:54:06 +01:00
parent 7da307c696
commit e03a8732a6

View File

@ -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<Args>(x)...);
new (static_cast<void*>(p)) T(boost::forward<Args>(x)...);
}
template <typename T>
@ -737,7 +737,7 @@ namespace boost { namespace unordered { namespace detail {
boost::unordered::detail::has_construct<Alloc, T>::value>::type
construct(Alloc&, T* p, T const& x)
{
new ((void*) p) T(x);
new (static_cast<void*>(p)) T(x);
}
template <typename T>
@ -779,7 +779,7 @@ namespace boost { namespace unordered { namespace detail {
boost::is_same<T, value_type>::value,
void*>::type = 0)
{
new ((void*) p) T(x);
new (static_cast<void*>(p)) T(x);
}
template <typename T>
@ -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 <typename T> T* const_cast_pointer(T* x) { return x; }
template <typename T> T* const_cast_pointer(T const* x) {
return const_cast<T*>(x);
}
// TODO: When possible, it might be better to use std::pair's
// constructor for std::piece_construct with std::tuple.
template <typename Alloc, typename Key>
@ -1339,11 +1347,13 @@ namespace boost { namespace unordered { namespace detail { namespace func {
{
node_constructor<Alloc> 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<Key>(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<Alloc> 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<Key>(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<Mapped>(m));
return a.release();
}