Итерация по коллекции различных типов в C ++ - PullRequest
2 голосов
/ 28 июля 2011

Ситуация

У меня есть шаблон класса TIppImage<T> для изображения типа T.У меня есть одноэлементный класс CIppMemoryManager, который может хранить несколько изображений разного размера и типа.

class CIppMemoryManager
{
public:
  /// ... Singleton interface ... 

  template<class T> TIppImage<T>* GetImage(width, height);

private:
  CIppMemoryManager();
  ~CIppMemoryManager();

  std::map<IppDataType, void*> m_Containers;
};

IppDataType - это enum, значения которого соответствуют фактическим типам.Все управление осуществляется в шаблонном классе TIppImageContainer<T>.И вся специализация этого класса хранится в m_Containers как void*.Это не очень хорошо, но, по крайней мере, просто.

При таком подходе я могу просто реализовать шаблон GetImage метод следующим образом:

template<class T> TIppImage<T>* CIppMemoryManager::GetImage(width, height)
{
  return reinterpret_cast<TIppImageContainer<T>*>(m_Containers[
    TIppTypeTraits<T>::ipp_data_type])->GetImage(width, height);
}

, где я использую класс чертTIppTypeTraits<T> для получения значения перечисления из данного типа.

Проблема

Я не могу просто реализовать не шаблонные методы, такие как конструктор.Мне нужно явно обработать все возможные типы:

CIppMemoryManager::CIppMemoryManager()
{
  m_Containers[ipp8u] = new CIppImageContainer<Ipp8u>;
  m_Containers[ipp8s] = new CIppImageContainer<Ipp8s>;
  m_Containers[ipp16u] = new CIppImageContainer<Ipp16u>;
  m_Containers[ipp16s] = new CIppImageContainer<Ipp16s>;
  ...
}

Хуже, для деструктора мне также нужно иметь дело с void*:

CIppMemoryManager::~CIppMemoryManager()
{
  delete reinterpret_cast<TIppImageContainer<Ipp8u>*>(m_Containers[ipp8u]);
  delete reinterpret_cast<TIppImageContainer<Ipp8s>*>(m_Containers[ipp8s]);
  delete reinterpret_cast<TIppImageContainer<Ipp16u>*>(m_Containers[ipp16u]);
  delete reinterpret_cast<TIppImageContainer<Ipp16s>*>(m_Containers[ipp16s]);
  ...
}

Итак, вопросы:

а) Есть ли способ перебора коллекции разных типов?Здесь нельзя использовать класс признаков, так как функция не является шаблоном.

б) Есть ли лучший способ хранения коллекции контейнеров - объектов другого типа?Когда они являются просто другой специализацией общего класса шаблона, сами контейнеры довольно просты.

Ответы [ 4 ]

2 голосов
/ 28 июля 2011

Я думаю, что вариант класса из библиотеки наддува (boost::variant) может вам помочь.Вы можете использовать посетителей для выполнения соответствующего кода в зависимости от типа, сохраненного в варианте.std::vector<boost::variant<T0, T1,...>> может хранить список объектов разных типов.

Поскольку ваши объекты похожи, они могут иметь одинаковый размер в памяти, что хорошо, так как boost::variant хранилище основано на стеке (без выделения кучи - это быстрее).

1 голос
/ 28 июля 2011

boost::mpl::for_each специально для этой работы. Определите вектор типов для работы, функтор или лямбда-выражение, чтобы сделать что-то, и все готово.

1 голос
/ 28 июля 2011

Что не так с полиморфным CIppImageContainer<T> (сделать так, чтобы все они имели общий базовый класс) и умным указателем?

Или что-то вроде boost::variant?

0 голосов
/ 28 июля 2011

boost::variant является наиболее вероятным кандидатом, но иногда variant S становятся довольно большими, поскольку они требуют некоторого дополнительного места для хранения, а также имеют дело с выравниванием.Так что, возможно, boost::any имеет преимущества и в некоторых ситуациях:

std::vector<std::pair< Type, boost::any > > data;

Комфортно выполнять итерации по такому контейнеру сложнее (boost::transform_iterator не может иметь более одного возвращаемого типа, поэтому это не будет работать без какого-либо шаблонаобман).

...