This is the mail archive of the libstdc++@gcc.gnu.org mailing list for the libstdc++ project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

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


    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.

François


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



Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]