Boost logo

Boost :

From: David Abrahams (dave_at_[hidden])
Date: 2003-09-02 10:22:25


Gregory Colvin <gregory.colvin_at_[hidden]> writes:

>> I think part of my point was that *nobody* needs what they offer, if
>> you include construct/destroy.
>
> Or rather that some implementations have failed to use what they
> offer, and our standard unfortunately doesn't insist that they do.

It's not unfortunate if it adds nothing, which is what I believe.

> Another reason construct is needed is that Allocator::pointer might
> be a proxy, with operator* and operator-> but not necessarily a
> conversion to void* or even T*.

Doesn't matter; you can always get the address of an object. See
http://anubis.dkuug.dk/jtc1/sc22/wg21/docs/lwg-closed.html#390

>> In fact, construct requires undefined behavior for non-POD T
>> because you can't copy its T* argument which points into raw
>> storage.
>
> I don't understand what you mean by this. Are you claiming that
> it is undefined to copy just a pointer to raw storage?

Unless the pointer has the right type, yes.

> If so, then how is placement new not undefined?

It uses a void*, as shown in your code snippet below.

> The standard says:
>
> a.construct(p,t)
> Effect: new((void*)p) T(t)
>
>> I think I would rather see a MPL lambda expression or metafunction
>> class interface for allocator type parameters. It makes little sense
>> for the allocator's user to be choosing its value_type.
>>
>> Something like:
>>
>> some_allocator<_1>
>>
>> or
>>
>> struct select_allocator
>> {
>> template <class T>
>> struct apply
>> {
>> typedef some_allocator<T> type;
>> };
>> };
>>
>> with some_allocator's interface being like what's required for
>> std::allocator but not including misplaced interface bits such as
>> address/construct/destroy, and possibly max_size -- these can be added
>> by a std::allocator facade wrapper if neccessary.
>>
>> I'm not sure we need a simple version and a complicated version.
>
> I'm not clear how you intend the above to be used, or what you
> intend it to be a replacement for.

I intend it to be the sort of type parameter that gets passed to our
objects which need custom allocation in place of a standard allocator.
It's ridiculous, IMO, to pass allocator<T> to a node-based container
which is *never* going to allocate a T object. The container itself
should decide which type the allocator template gets instantiated on,
via:

    mpl::apply<mpl::lambda<S>, Node>::type

     [
       this is approximately the same as:

         S::template apply<U>::type == some_allocator<U>

       except that it works when S is the lambda expression
       some_allocator<_1> as well as when it's the select_allocator
       metafunction class below it.
     ]

What the rebind requirement in the allocator means for pool
allocation, for example, is that a pool_allocator<T> object must
either be stateless (in which case allocator inequality is
meaningless) or effectively be able to allocate blocks of *any* size
and alignment, rather than just as appropriate for T. It's a
conceptual mess.

-- 
Dave Abrahams
Boost Consulting
www.boost-consulting.com

Boost list run by bdawes at acm.org, gregod at cs.rpi.edu, cpdaniel at pacbell.net, john at johnmaddock.co.uk