This is the mail archive of the
gdb-patches@sourceware.org
mailing list for the GDB project.
Re: [PATCH] Introduce gdb::byte_vector, add allocator that default-initializes
- From: Pedro Alves <palves at redhat dot com>
- To: Yao Qi <qiyaoltc at gmail dot com>
- Cc: gdb-patches at sourceware dot org
- Date: Fri, 23 Jun 2017 12:51:08 +0100
- Subject: Re: [PATCH] Introduce gdb::byte_vector, add allocator that default-initializes
- Authentication-results: sourceware.org; auth=none
- Authentication-results: ext-mx09.extmail.prod.ext.phx2.redhat.com; dmarc=none (p=none dis=none) header.from=redhat.com
- Authentication-results: ext-mx09.extmail.prod.ext.phx2.redhat.com; spf=pass smtp.mailfrom=palves at redhat dot com
- Dkim-filter: OpenDKIM Filter v2.11.0 mx1.redhat.com F1DD16586F
- Dmarc-filter: OpenDMARC Filter v1.3.2 mx1.redhat.com F1DD16586F
- References: <1497287225-16542-1-git-send-email-palves@redhat.com> <86a84zht7y.fsf@gmail.com>
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