This is the mail archive of the gdb-patches@sourceware.org mailing list for the GDB 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: [PATCH] Introduce gdb::byte_vector, add allocator that default-initializes


On 06/23/2017 11:52 AM, Yao Qi wrote:
> Pedro Alves <palves@redhat.com> writes:
> 
> Hi Pedro,
> I happen to read this code when I am writing a stack allocator,
> 
>> +  /* Override rebind.  */
>> +  template<typename U>
>> +  struct rebind
>> +  {
>> +    /* A couple helpers just to make it a bit more readable.  */
>> +    typedef std::allocator_traits<A> traits_;
>> +    typedef typename traits_::template rebind_alloc<U> alloc_;
>> +
>> +    /* This is what we're after.  */
>> +    typedef default_init_allocator<U, alloc_> other;
> 
> Can we just replace "alloc_" with "A"?  alloc_ is a typedef, which is
> "typename std::allocator_traits<A>::template rebind_alloc<U>".  Then, it
> is "typename A::rebind<U>::other".  

First, this direct substitution is not guaranteed.  We don't know
whether "A::rebind<U>::other" exists, since it is optional:

 http://en.cppreference.com/w/cpp/concept/Allocator

We're not supposed to access properties/fields/methods of allocators
directly; instead, we need to indirect via std::allocator_traits, which 
provides defaults:

 http://en.cppreference.com/w/cpp/memory/allocator_traits

 "rebind_alloc<T>" => Alloc::rebind<T>::other if present,
                      otherwise Alloc<T, Args> if this Alloc is Alloc<U, Args>

> Then, it is "A<U>", so the member
> "other" can be "typedef default_init_allocator<U, A> other;".

Not really.  "A<U>" is not A.  "A<U>" wouldn't compile, either.

When A is "std::allocator<T>", "other" for U must be:

  typedef default_init_allocator<U, std::allocator<U>> other;

Not:

  typedef default_init_allocator<U, std::allocator<T>> other;



In more detail, we have:

 template<typename T, typename A = std::allocator<T>>
 class default_init_allocator : public A

The point of "other" is to return a default_init_allocator
for U.  IOW, above, we need to replace both "T"s with "U".

 template<typename U, typename B = std::allocator<U>>
 class default_init_allocator : public B

("A" replaced with "B" too, to avoid confusion, since
it ends up being a different type.)


So:

  default_init_allocator<T>::rebind<U>::other

should result in

  default_init_allocator<U, std::allocator<U>>

while with what you're saying, it'd result in:

  default_init_allocator<U, std::allocator<T>>


IOW, say that T is int, and U is char.  Then,

  default_init_allocator<int>::rebind<char>::other

should be:

  default_init_allocator<char, std::allocator<char>>

not:

  default_init_allocator<char, std::allocator<int>>

Hope that helps,
Pedro Alves


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