使用 typedef 从分配器创建共享指针?
我正在对一些代码进行改造,以使用分配器
,而不是直接使用operator new
和operator delete
。这段代码的公共接口的一部分不是返回一个秃头指针,而是一个 shared_ptr
(由徘徊于 new
的秃头指针构造而成。)
我在公共合约中看到对于分配器,有多个名为 pointer
、const_reference
等的 typedef。这个想法是,我可能会使用而不是直接引用类型 T *
指针
,允许分配器作者插入 C 指针以外的东西。
但我又将普通指针包装在智能指针中,它需要一个诚实的 C 指针(我认为)。如果我尝试将代码更改为使用分配器的 typedef,我会遇到麻烦吗?我还没有尝试过(因为只是为了尝试还需要做一些跑腿工作)所以我先问..
编辑:这是我想要更改的一些代码(我没有第一次不包含在内,因为它不太友好。)
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;
}
特别是,在 initializer( Injector)
当前嵌入的表达式直接使用new
和delete
。我希望它使用 Allocator
来代替,并将它们切换到放置新/显式销毁,以做出类似的事情
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));
}
};
问题是,我应该尝试尊重分配器的 typedef 吗?看起来我应该是这样,否则我没有正确使用分配器(不用介意,实际上,几乎所有分配器都会有“无聊”的 typedef 值。)
我当然可以调整它以返回 Allocator::指针
而不是Impl *
,直到我尝试将其推入shared_ptr
。也许它也在那里起作用?这是我的问题。也许比我更熟悉该标准的人可能会说“只要 Allocator::pointer
像 operator*
一样嘎嘎叫,并且您注册了一个自定义删除器,您就会没事吧。”
编辑: @bdonlan 提出了一个很好的观点,即 shared_ptr
是基于 Allocator::value_type
而不是 Allocator 进行模板化的: :指针
。相反,它可能在内部保存一个 Allocator::value_type *
。这似乎回答了这个问题,除了分配器作者可能会选择在其 Allocator::pointer
上实现 operator Allocator::value_type *
,即使在使用时转换后的值,它根据一些具体陈述的语义“一切正常”。
标准是否要求分配器作者这样做?
编辑:请参阅相关。
I have some code that I am retrofitting to use an allocator
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.
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(1)
shared_ptr
(以及其他 TR1 智能指针)是根据元素类型(而不是指针类型)定义的(即采用模板参数)。因此,如果您使用的是shared_ptr
,则无法替换您自己的指针表示形式;在大多数情况下这样做也是没有意义的。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 usingshared_ptr
, you cannot substitute your own pointer representation; nor does it make sense to do so in most cases.