On Thu, 17 Oct 2024 at 21:39, Jonathan Wakely <jwakely....@gmail.com> wrote:
> > > On Thu, 17 Oct 2024 at 20:52, François Dumont <frs.dum...@gmail.com> > wrote: > >> Here is an updated version that compiles, I think, all your feedbacks. >> It's much cleaner indeed. >> > > Thanks, I'll take a look tomorrow. > > >> It's also tested in C++98/17/23. >> >> I'm surprised that we do not need to consider potential >> allocator::const_pointer. >> > Do you mean consider the case where Alloc::const_pointer is not the same > type as rebinding 'pointer' to a const element type? > > We don't need to consider that because we never get a 'const_pointer' from > the allocator, and we never need to pass a 'const_pointer' to the > allocator. The allocator's 'allocate' and 'deallocate' members both work > with the 'pointer' type, so we only need to use that type when interacting > with the allocator. For all the other uses, such as _Const_Node_ptr, what > we need is a pointer-to-const that's compatible with the allocator's > pointer type. It doesn't actually matter if it's the same type as > allocator_traits<Alloc>::const_pointer, because we don't need > Sorry, I sent the email before finishing that thought! ... we don't need to pass a const_pointer to anything, we only need it for the container's own purposes. But thinking about it some more, do we even need a const-pointer for the container? Currently the const_iterator stores a const-pointer, and some members like _M_root() and _M_leftmost() return a const-pointer. But they don't need to. The nodes are all pointed to by a non-const _Base_ptr, none of the storage managed by the container is const. We could just use the non-const pointers everywhere, which would make things much simpler! The const_iterator stores a const_pointer, and returns a const-pointer from operator->(), so maybe _Rb_tree_const_piterator should take the allocator's const_pointer as its template argument, instead of the non-const ValPtr. So the trait would take two pointer types, but the const one would only be used for the const iterator: template<typename _ValPtr, typename _CValPtr> struct _Rb_tree_node_traits { using _Node_base = _Rb_tree_pnode_base<_ValPtr>; using _Node_type = _Rb_tree_pnode<_ValPtr>; using _Header_t = _Rb_tree_pheader<_Node_base>; using _Iterator_t = _Rb_tree_piterator<_ValPtr>; using _Const_iterator_t = _Rb_tree_const_piterator<_CValPtr>; }; Would that work? I can experiment with that if you like. > > >> Is there a plan to deprecate it ? >> > > No, although I think that would be possible. Nothing in the allocator > requirements ever uses that type or cares what it is, as long as it's > convertible to 'const_void_pointer', and 'pointer' is convertible to > 'const_pointer'. > > >> And if not, should not alloc traits const_pointer be per default a rebind >> of pointer for const element_type like in the __add_const_to_ptr you made >> me add ? I can try to work on a patch for that if needed. >> > > No, allocator_traits is defined correctly as the standard requires. If an > allocator A defines a 'A::const_pointer' typedef, then that is used. If > not, then 'allocator_traits<A>::const_pointer' defaults to rebinding the > non-const 'allocator_traits<A>::pointer' type. > > >