使用 typedef 从分配器创建共享指针?

发布于 2024-12-05 09:57:44 字数 3265 浏览 0 评论 0原文

我正在对一些代码进行改造,以使用分配器,而不是直接使用operator newoperator delete。这段代码的公共接口的一部分不是返回一个秃头指针,而是一个 shared_ptr (由徘徊于 new 的秃头指针构造而成。)

我在公共合约中看到对于分配器,有多个名为 pointerconst_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) 当前嵌入的表达式直接使用newdelete。我希望它使用 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::pointeroperator* 一样嘎嘎叫,并且您注册了一个自定义删除器,您就会没事吧。”

编辑: @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 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

热血少△年 2024-12-12 09:57:44

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 using shared_ptr, you cannot substitute your own pointer representation; nor does it make sense to do so in most cases.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文