Boost logo

Boost :

From: E. Gladyshev (egladysh_at_[hidden])
Date: 2003-08-26 14:42:43


--- Peter Dimov <pdimov_at_[hidden]> wrote:

[...]
> template<class A> struct X
> {
> typedef typename A::value_type T;
>
> static T * create(A & a)
> {
> T * p = a.allocate(1);
>
> try
> {
> new(p) T;
> }
> catch(...)
> {
> a.deallocate(p, 1);
> throw;
> }
>
> return p;
> }
>
> static void destroy(A & a, T * p)
> {
> p->~T();
> a.deallocate(p, 1);
> }
> };
>
> The above doesn't respect A::pointer etc.
>
> Now you can _almost_ do the straightforward thing:
>
> template< class T, class A = std::allocator<T> >
> struct Y
> {
> shared_ptr<T> _data;
> std::list<T, A> _list;
> Y(): _data( X<A>::create(), X<A>::destroy ) {...}
> };

I would change the definition of create/destroy in X<>:

static T * create(A & a = A() );
static void destroy(T * p, A & a= A());

Anyway it seems like a good solution, but it won't work pretty
for the reasons that you described later in your post.
shared_ptr should keep its own copy of A just like std::list does.
Then it'll be consistent with what people are used to in STL.

>
> except that X<A>::create and ::destroy take a reference to an allocator.
> This should remind you that you forgot the allocator argument in the
> constructor:

Good point, I just ommitted it for simplicity sake.

>
> Y(A const & a = A()): ...
>
> Now _list will make itself a copy of that 'a'. This immediately hints at a
> potential problem:
>
> template< class T, class A = std::allocator<T> > struct Z
> {
> std::list<T, A> _list;
> std::list<T, A> _list2;
> };
>
> where _list and _list2 will make their own copies and can't be made to share
> a single allocator instance. But let's ignore that (presumably the author of
> a stateful A will use a <drumroll> shared_ptr<> underneath so that copies
> use the same heap) and get back to our list+shared_ptr.

Yes, I am aware of this problem, shared_ptr or a static heap member will work.
>From my experience, it is exactly the case. Typically you don't want to
keep per-instance data in A.

> Now who should own the allocator that is used to construct or later destroy
> *_data? Should we use _list.get_allocator() for that? We can't since a copy
> of Y will copy _list but share _data, and the original may get destroyed
> along with the allocator. So we'll need to do something along the lines of:
>
> Y(A const & a = A()): _list(a), _data()
> {
> A a2(a); // original is const
> T * p = X<A>::create(a2); // evaluation order
> _data.reset( p, bind(X<A>::destroy, a2, _1) );
> }
>
> Not very pretty, but that's what you need to pay for being
> std::allocator-based; its interface is tailored for containers. For such a

Exactly, like I said before, shared_prt should keep its own copy of A.

> case I'd definitely consider going back to
>
> template< typename T > struct A
> {
> shared_ptr<T> _data;
> std::list<T> _list;
> };
>
> unless there are very solid reasons for the allocator parameter. ;-)

I agree, but the problme is that I don't know whether I have a solid reason or not.
I have to ship my class to someone else. She might have a solid reason, I don't know.
If I supply an allocator parameter, then I am covered and I can sleep well. :)

>
> Or you can write your own alloc_ptr<T, A>, of course, if you want to go the
> allocator route; it is quite a different beast compared to shared_ptr as it
> doesn't support polymorphism, for example, so it deserves its own name.

Perhaps, alloc_ptr should be included in boost. It'll give us a standard way to integrate boost
and STL.

>
> But your code still looks somewhat artificial to me; why would you want to
> deep copy _list but shallow copy _data? It doesn't make much sense.

It is just an example. I agree, it does look artificial, but you can imaging something along the
lines:

template< typename T, template <typename> A >
{
  shared_ptr< T, A<T> > _data;
  shared_ptr< std::list< T,A<T> >, A<std::list<T,A<T> > > > _list;
};

It uses template template parameters and both _data and _list are shared.

Eugene

__________________________________
Do you Yahoo!?
Yahoo! SiteBuilder - Free, easy-to-use web site design software
http://sitebuilder.yahoo.com


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