Как я могу сделать RefCounting необязательным внутри шаблонного полицейского класса? - PullRequest
0 голосов
/ 04 февраля 2020

В моих распределителях пулов есть внутренний класс Block, который выглядит следующим образом:

template<class T> PoolAlloc{
...
 struct Block{
  T userData;
  RefCounting rc;
 };
 Block * m_pPool;
...
};

Я не знаю, как сделать пересчет необязательным и элегантным. Передача внешнего блока в качестве дополнительного параметра шаблона уродлива, поскольку мне придется передать параметр T как распределителю, так и параметру распределителя:

PoolAlloc<Foo, Block<Foo>>

Это избыточно. Я пытался специализировать только внутреннюю структуру, но мое понимание этого не вариант, внутренние классы требуют полной специализации внешнего класса:

template<class T, bool refCounting> PoolAlloc{
...
 struct Block;
...
};
template <class T, bool RC> struct PoolAlloc<T,RC>::Block{ T userData; RefCounting rc;};// default
template<class T> struct PoolAlloc<T, false>::Block{ T userData;}; // cant get this to compile

1 Ответ

0 голосов
/ 04 февраля 2020

Ответ, скорее всего, проще, чем вы думаете.

Представьте, что у вас есть структура / класс, и вы хотите сделать что-то внутри нее необязательным (то есть, там или нет), это «политика» для отсутствия лучшее слово. Первое, что вам нужно сделать, это определить 2 структуры, одну с реальной реализацией, а другую с пустой реализацией, затем в зависимости от того, какой экземпляр вы хотите создать. Нет другого способа реализации этого BTW, поэтому вам придется обойтись здесь с некоторой избыточностью. (По умолчанию template параметры и template using могут помочь немного уменьшить избыточность.)

Например (не проверено):

struct empty_ref_counter {
    //empty reference counter implementation
    void add_reference() {} // <-- no implementation!!
    //other empty member functions
};

struct ref_counter {
    //reference counter implmentation
    unsigned ref;
    void add_reference() {
         ++ref;
    }
    //other complete member functions
};

template<typename RefCountPolicy = empty_ref_counter>
struct strA {
    typedef typename RefCountPolicy ref_policy;
    RefCountPolicy count;
};

Примечание. Я сделал typedef typename из ref_policy это справочная политика, используемая strA и может использоваться для проверки ref_policy внешними источниками (или функциями, которые принимают strA<RCP>).

Другими словами, вы можете сделать Block template struct и по-прежнему иметь доступ к T во внешнем template class / struct.

 struct BlockBase {};
 template<typename RefCount>
 struct Block : BlockBase {
  T userData;
  RefCount rc;
 };
 BlockBase* m_pPool;

. Для этого также может быть хорошей идеей дать Заблокируйте не шаблонную базу (возможно, даже с виртуальным деструктором, чтобы убедиться, что RefCount правильно уничтожен !!)

...