情况
我有一个用于 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.
发布评论
评论(4)
我认为 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. Astd::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).多态
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
?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.boost::variant
是最有可能的候选者,但有时variant
S 会变得相当大,因为它们需要一些额外的存储并且还必须处理对齐。因此,也许boost::any
在某些情况下也有优势:要轻松地迭代这样的容器会更困难(
boost::transform_iterator
不能有多个返回类型,所以如果没有一些模板技巧,这将无法工作)。boost::variant
is the most likely candidate but sometimesvariant
S become rather large as they require some extra storage and also have to deal with alignment. So maybeboost::any
has advantages in some situations as well: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).