Создание shared_ptr из распределителя с помощью typedefs? - PullRequest
0 голосов
/ 18 сентября 2011

У меня есть код, который я модифицирую, чтобы использовать allocator вместо operator new и operator delete напрямую. Одна часть открытого интерфейса этого кода - возвращать не лысый указатель, а shared_ptr (созданный из лысого указателя, блуждающего из new.)

Я вижу в публичном контракте для распределителя несколько определений типов с именами pointer, const_reference и т. Д. Идея состоит в том, чтобы вместо прямого обращения к типам T * я мог бы использовать pointer, позволяя автору распределителя проскользнуть во что-то, кроме указателя C.

Но я, в свою очередь, оборачиваю обычный указатель в умный указатель, которому нужен честный указатель C (я думаю.) Если я попытаюсь изменить свой код на использование typedefs распределителя, возникнут ли у меня проблемы? Я еще не пробовал (так как нужно просто немного потрудиться), поэтому сначала спрашиваю ..

РЕДАКТИРОВАТЬ: Вот часть кода, который я хочу изменить (я не включил в первый раз, потому что это не очень дружелюбно.)

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

В частности, методы шаблонов construct и destroy, вызываемые в результате выражения 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));
  }
};

Вопрос заключается в том, должен ли я попытаться соблюдать typedefs распределителя? Похоже, что так и должно быть, иначе я неправильно использую распределитель (не говоря уже о том, что практически все они будут иметь "скучные" значения typedef.)

Я, конечно, могу подтолкнуть его, чтобы вернуть Allocator::pointer вместо Impl *, пока я не попытаюсь засунуть его в shared_ptr. А может, там тоже все работает? Это мой вопрос. Возможно, кто-то, более знакомый со стандартом, чем я, мог бы сказать что-то вроде: «Пока Allocator::pointer крякает как operator*, и вы регистрируете пользовательский удалитель, у вас все будет хорошо».

РЕДАКТИРОВАТЬ: @bdonlan поднимает превосходную точку, что shared_ptr шаблонируется на то, что будет Allocator::value_type, а не Allocator::pointer. Вместо этого он предположительно содержит Allocator::value_type * внутри. Похоже, это отвечает на этот вопрос, за исключением того, что автор распределителя может решить реализовать operator Allocator::value_type * в своих Allocator::pointer таким образом, что даже при использовании преобразованного значения оно «все работает» в соответствии с какой-то конкретной заявленной семантикой.

Требует ли стандарт, чтобы это сделали авторы распределителя?

РЕДАКТИРОВАТЬ: См. относящиеся.

1 Ответ

0 голосов
/ 18 сентября 2011

shared_ptr (и другие интеллектуальные указатели TR1) определены (т.е. принимают параметры шаблона) в терминах типа элемента, не тип указателя. Таким образом, если вы используете shared_ptr, вы не можете заменить свое собственное представление указателя; и в большинстве случаев это не имеет смысла.

...