--- 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