Add std::unordered_* C++11 allocator support

François Dumont
Tue Apr 9 20:23:00 GMT 2013

     Thanks for your remarks. I am going to implement them.

     However I already know that removing _Mutable_Value_Type I will 
face the problem of std::is_copy_assignable not giving the correct 
result for std::pair<const int, int>. I will surely have to explicitly 
forbid usage of assignment as soon as the type is std::pair, whatever 
std::is_copy_assignable is saying.


On 04/08/2013 10:24 AM, Jonathan Wakely wrote:
> On 6 April 2013 19:53, Jonathan Wakely wrote:
>> I'm not very comfortable with the "mutable value type" part which
>> accesses the stored value through a pointer to a different type. This
>> violates strict aliasing rules and would also give the wrong result if
>> users provide an explicit specialization of std::pair<int, Foo> which
>> stores pair::second before pair::first, then tries to store that type
>> in an unordered_map.  When a pair<const int, Foo>* is cast to
>> pair<int, Foo>* the user's explicit specialization would not be used
>> and the layout would be wrong.  Would it be possible to separate the
>> C++11 allocator support from the new feature that attempts to reuse
>> existing nodes?  Or maybe remove the mutable value type stuff so that
>> nodes can be reused for unordered sets but not unordered maps?
> For a non-assignable value_type we can reuse the node (but not the
> value_type) by destroying and constructing a new value_type in place:
>        __node_type*
>        operator()(const __node_type* __n) const
>        {
>      if (_M_nodes)
>        {
>          __node_type* __node = _M_nodes;
>          allocator_traits<A>::destroy(a, __node->_M_valptr());
>          __try {
>            allocator_traits<A>::construct(a, __node->_M_valptr(),
> *__n->_M_valptr());
>            // Construction didn't throw, we can unlink the node.
>            _M_nodes = _M_nodes->_M_next();
>            __node->_M_nxt = nullptr;
>            return __node;
>          } __catch (...) {
>            // TODO deallocate node
>            __throw_exception_again;
>          }
>        }
>      return _M_h._M_allocate_node(__n->_M_v());
>        }
> This can be much less efficient than assignment if the value_type has
> its own allocated memory, but I don't see any alternative. Casting
> pair<const A,B>& to pair<A,B>& is not an option.
> N.B. the code above

More information about the Libstdc++ mailing list