Creating a shared_ptr from an allocator using typedefs?
I have some code that I am retrofitting to use an alloc开发者_如何学运维ator
instead of operator new
and operator delete
directly. One part of this code's public interface is to return not a bald pointer but a shared_ptr
(being constructed from the bald pointer wandering out of new
.)
I see in the public contract for an allocator several typedefs named pointer
, const_reference
, etc. The idea is instead of referring to types T *
directly, I might use pointer
, allowing an allocator author to slip in something other than a C pointer.
But I am in turn wrapping the normal pointer in a smart pointer, which wants an honest C pointer (I think.) If I attempt to change my code over to using the allocator's typedefs, will I run into trouble? I haven't tried yet (as there is a bit of leg work to do just to try) so I'm asking first..
EDIT: Here's the some of code I want to alter (I didn't include the first time, as it isn't very friendly.)
template<typename Injector, typename Iface, typename Allocator, typename Impl, typename A1>
class New<Injector, Iface, Allocator, Impl, Impl(A1)>: public Binding<Injector> {
public:
static Impl * provide(Injector const & injector) {
SAUCE_SHARED_PTR<A1> a1(injector.template provide<A1>());
return initializer(injector).template construct<Impl, SAUCE_SHARED_PTR<A1> >(a1);
}
static void dispose(Injector const & injector, Iface * iface) {
Impl * impl = static_cast<Impl *>(iface);
initializer(injector).destroy(impl);
}
};
// Elsewhere
template<typename Iface>
SAUCE_SHARED_PTR<Iface> provide() const {
Iface * provided = provideFromBinding<Iface>(
Module::template bindings<Injector_> );
SAUCE_SHARED_PTR<Iface> smartPointer;
smartPointer.reset(provided, deleter);
return smartPointer;
}
In particular, the construct
and destroy
template methods called on the result of the initializer(injector)
expression currently embed direct uses of new
and delete
. I'd like it to use the Allocator
instead, and switch them to placement new / explicit destruction, to make something like
template<typename Injector, typename Iface, typename Allocator, typename Impl, typename A1>
class New<Injector, Iface, Allocator, Impl, Impl(A1)>: public Binding<Injector> {
public:
static Impl * provide(Injector const & injector) {
SAUCE_SHARED_PTR<A1> a1(injector.template provide<A1>());
Allocator allocator;
Impl * impl = allocator.allocate(sizeof(Impl));
initializer(injector).template construct<Impl, SAUCE_SHARED_PTR<A1> >(impl, a1);
return impl;
}
static void dispose(Injector const & injector, Iface * iface) {
Allocator allocator;
Impl * impl = static_cast<Impl *>(iface);
initializer(injector).destroy(impl);
allocator.deallocate(impl, sizeof(Impl));
}
};
The question is, should I try to honor the allocator's typedefs? It seems like I ought to be or else I'm not using the allocator correctly (never mind that pragmatically speaking nearly all of them will have the "boring" typedef values.)
I can certainly jigger it to return Allocator::pointer
instead of Impl *
, up until I attempt to shove it into a shared_ptr
. And maybe it just works there too? That is my question. Perhaps someone more familiar with the standard than me could say something like "So long as Allocator::pointer
quacks like a operator*
and you register a custom deleter, you'll be fine."
EDIT: @bdonlan raises the excellent point that a shared_ptr
is templated on what would be Allocator::value_type
, and not Allocator::pointer
. Instead, it presumably holds a Allocator::value_type *
internally. This seems to answer the question, except an allocator author might choose to implement operator Allocator::value_type *
on their Allocator::pointer
in such a way that, even when using the converted value, it "all works out" according to some concretely-stated semantic.
Does the standard require allocator authors to do this?
EDIT: See related.
shared_ptr
(and the other TR1 smart pointers) are defined (ie, take template parameters) in terms of the element type, not the pointer type. As such, if you are using shared_ptr
, you cannot substitute your own pointer representation; nor does it make sense to do so in most cases.
精彩评论