开发者

Iterating through collection of different types in C++

Situation

I have a template class TIppImage<T> for image of type T. I have singleton class CIppMemoryManager which can store a number of images of different size and type.

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

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

private:
  CIppMemoryManager();
  ~CIppMemoryManager();

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

IppDataType is enum, which values correspond to actual types. All management is done in template class TIppImageContainer<T>. And all specialization of this class is stored in m_Containers as a void*. It's not very good, but it is at least simple.

With this approach, I can simply implement template GetImage method like this:

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

where I'm using traits class TIppTypeTraits<T> to obtain enum value from given type.

Problem

I cannot simply implement non-template methods like constructor. I need to explicitly handle all possible types:

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

Worse, for destructor I also need to deal with void*:

CIppMemoryManager::~CIppMemoryManager()
{
  delete reinterpret_cast开发者_StackOverflow中文版<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]);
  ...
}

So, the questions are:

a) Is there some way to iterate through collection of different types? Cannot use traits class here since function is non-template.

b) Is there some better way to store collection of containers - objects of different type? When they are just a different specialization of common template class, containers itself are pretty simple.


I think the class variant from the boost library (boost::variant) may help you. You can use visitors to execute the appropriate code depending on the type stored in a variant. A std::vector<boost::variant<T0, T1,...>> can store a list of objects of different types.

As your objects are similar, they may have the same size in memory, which is a good thing since boost::variant storage is stack-based (no heap allocation - this is faster).


What's wrong with polymorphic CIppImageContainer<T> (make them all share a common base class) and a smart pointer ?

Or some kind of boost::variant ?


boost::mpl::for_each is tailor-made for that job. Define a vector of types to operate on, a functor or lambda expression to do something, and you are done.


boost::variant is the most likely candidate but sometimes variantS become rather large as they require some extra storage and also have to deal with alignment. So maybe boost::any has advantages in some situations as well:

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

To comfortably iterate over such a container is harder (boost::transform_iterator cannot have more than one return type, so this wont work without some template trickery).

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜