通过C ++中的不同类型的集合进行迭代

时间:2011-07-28 16:42:46

标签: c++ templates void-pointers typetraits typelist

场合

对于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是枚举,其值对应于实际类型。所有管理都在模板类TIppImageContainer<T>中完成。此类的所有专精都存储在m_Containersvoid*。它不是很好,但它至少是简单的。

通过这种方法,我可以简单地实现模板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);
}

我正在使用traits类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]);
  ...
}

所以,问题是:

a)有没有办法迭代不同类型的集合?因为函数是非模板,所以不能在这里使用traits类。

b)是否有更好的方法来存储容器集合 - 不同类型的对象?当它们只是普通模板类的不同专业化时,容器本身就非常简单。

4 个答案:

答案 0 :(得分:2)

我认为来自boost库(boost::variant)的类变体可能会对您有所帮助。您可以使用访问者根据变体中存储的类型执行相应的代码。 std::vector<boost::variant<T0, T1,...>>可以存储不同类型的对象列表。

由于您的对象相似,它们在内存中的大小可能相同,这是一件好事,因为boost::variant存储是基于堆栈的(没有堆分配 - 这样更快)。

答案 1 :(得分:1)

多态CIppImageContainer<T>(让它们共享一个共同的基类)和智能指针有什么问题?

或某种boost::variant

答案 2 :(得分:1)

boost::mpl::for_each是为这项工作量身定做的。定义要操作的类型向量,函子或lambda表达式来做某事,你就完成了。

答案 3 :(得分:0)

boost::variant是最有可能的候选人,但有时variant S变得相当大,因为他们需要一些额外的存储并且还必须处理对齐。所以也许boost::any在某些情况下也有优势:

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

要轻松地迭代这样的容器更难(boost::transform_iterator不能有多个返回类型,所以如果没有一些模板技巧,这将无法工作。)