Gregory Colvin <[EMAIL PROTECTED]> writes: > On Tuesday, Sep 2, 2003, at 09:22 America/Denver, David Abrahams wrote: > >> Gregory Colvin <[EMAIL PROTECTED]> writes: >> ... >>> Dave: >>>> 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. > > But given rebind() it doesn't really matter.
Well, it's rebind<...> actually, and it does matter. See below. > We could just as well have specified that all containers take > allocator<void> arguments. It's just horribly decomposed (gross! ;-> ). It says "pass me a complicated class which I might never actually use, but which also functions as a nested metafunction which I might use to get the class which I will use. The class you pass has to meet all kinds of irrelevant requirements like having a nested value_type that matches my element type, and the class I will actually use also has to meet all kinds of requirements irrelevant to its use like having a nested rebind template." >> 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. >> ] >> > > Sorry, but I'm still not following this, but that may be > because I don't know much MPL, so I can only guess at what > you are up to. I probably need a detailed example of how to > write and use one of these thingys to make any sense of your > proposal. I showed one which requires no MPL knowledge S::template apply<U>::type is the correct (non-standard) 'allocator' type for U given an AllocatorSelector S (see the allocator_selector class from my previous post) This is essentially equivalent to what normally happens with A::template rebind<U>, except that it happens uniformly, and classes are doing one job instead of two or three. There are reasons for using apply<U>::type instead of simply rebind<U>, but those are not too important to my argument. > Does your proposal support stateful allocators? It could, pretty easily. I'd use an allocator_state traits template which generates the type used to initialize the allocator. The standard model is that allocator_state<A>::type is just A, but it doesn't make any sense for allocators which need rebind to require the allocator type. >> 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) > > Yes, all stateless allocators compare equal, and stateless > allocators are the easiest kind to make compare equal, as > the standard currently requires allocators to do. > >> or effectively be able to allocate blocks of *any* size >> and alignment, rather than just as appropriate for T. > > Yes, because node-based containers need to allocate nodes, > perhaps of various kinds, but they don't expose their > node types in their interface. So you have to pass in > something, and we went with T rather than void or whatever. I think you're missing my point. There's no reason that a stateful allocator<T> should have access to the state data required to allocate U objects, but that's the status quo. > It might have been better to have different allocator > interfaces for array-based versus node-based containers Maybe. > since array-based containers have no need of rebind() Not neccessarily. My fixed-size single allocation array needed it. > and node-based containers have no need of allocator<T>. Maybe. I have my doubts. The only thing that keeps users of vector<T> safe from mistakenly supplying allocator<U> is the default argument. >> It's a conceptual mess. > > Alex didn't have MPL when he invented allocators. So they are > messier than they need to be, but I still say they are not so > bad as you claim Are you saying my factual claims are wrong, or just that all those issues don't amount to a very important problem? > and that it would be easier for the next standard to repair them > than to replace them. That may be, but we're here at Boost, talking about the interface we should be using in Boost components. -- Dave Abrahams Boost Consulting www.boost-consulting.com _______________________________________________ Unsubscribe & other changes: http://lists.boost.org/mailman/listinfo.cgi/boost