--- Peter Dimov <[EMAIL PROTECTED]> 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
_______________________________________________
Unsubscribe & other changes: http://lists.boost.org/mailman/listinfo.cgi/boost

Reply via email to