在 C++ 中迭代不同类型的集合

发布于 2024-11-26 23:20:54 字数 2004 浏览 1 评论 0 原文

情况

我有一个用于 T 类型图像的模板类 TIppImage。我有单例类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 中完成。该类的所有特化都作为 void* 存储在 m_Containers 中。虽然不是很好,但至少很简单。

通过这种方法,我可以简单地实现模板 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 从给定类型获取枚举值。

问题

我不能简单地实现非模板方法,例如构造函数。我需要显式处理所有可能的类型:

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)是否有某种方法可以迭代不同类型的集合?由于函数不是模板,因此无法在此处使用特征类。

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

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

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(4

时光沙漏 2024-12-03 23:20:54

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

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

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).

似梦非梦 2024-12-03 23:20:54

多态 CIppImageContainer (使它们共享一个公共基类)和智能指针有什么问题?

或者某种 boost::variant

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 ?

感受沵的脚步 2024-12-03 23:20:54

boost::mpl::for_each 是为这项工作量身定制的。定义一个要操作的类型向量、一个函子或 lambda 表达式来执行某些操作,然后就完成了。

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.

当梦初醒 2024-12-03 23:20:54

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

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

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

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).

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文