C++ 在C++;
形势 对于类型为C++ 在C++;,c++,templates,void-pointers,typetraits,typelist,C++,Templates,Void Pointers,Typetraits,Typelist,形势 对于类型为T的图像,我有一个模板类TIppImage。我有一个singleton类CIppMemoryManager,它可以存储许多不同大小和类型的图像 class CIppMemoryManager { public: /// ... Singleton interface ... template<class T> TIppImage<T>* GetImage(width, height); private: CIppMemoryManager
T
的图像,我有一个模板类TIppImage
。我有一个singleton类CIppMemoryManager
,它可以存储许多不同大小和类型的图像
class CIppMemoryManager
{
public:
/// ... Singleton interface ...
template<class T> TIppImage<T>* GetImage(width, height);
private:
CIppMemoryManager();
~CIppMemoryManager();
std::map<IppDataType, void*> m_Containers;
};
其中,我使用traits类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>;
...
}
因此,问题是:
a) 是否有某种方法可以遍历不同类型的集合?无法在此处使用traits类,因为函数是非模板的
b) 有没有更好的方法来存储容器集合-不同类型的对象?当它们只是普通模板类的不同专门化时,容器本身非常简单。我认为boost库中的类变体(
boost::variant
)可能会对您有所帮助。根据变量中存储的类型,可以使用访问者执行适当的代码。std::vector
可以存储不同类型对象的列表
由于对象相似,它们在内存中的大小可能相同,这是一件好事,因为
boost::variant
存储是基于堆栈的(没有堆分配-这会更快)。多态CIppImageContainer
(使它们都共享一个公共基类)和一个智能指针有什么问题
或者某种类型的
boost::variant
?boost::variant
是最有可能的候选,但有时variant
会变得相当大,因为它们需要一些额外的存储空间,还必须处理对齐问题。因此,在某些情况下,boost::any
可能也有优势:
std::vector<std::pair< Type, boost::any > > data;
std::vector>数据;
轻松地在这样的容器上进行迭代比较困难(
boost::transform\u迭代器不能有多个返回类型,因此如果没有一些模板技巧,这将无法工作)。boost::mpl::for\u每个
都是为该任务量身定制的。定义一个要操作的类型向量,一个函子或lambda表达式来执行某项操作,您就完成了。似乎可以解决使用虚拟析构函数进行销毁的问题。只是没有考虑模板类的非模板祖先。但是,<代码> GeMeTime/COD>不能是虚拟的,因为它使用模板参数。它将如何帮助迭代不同类型的集合?考虑一些<代码>变体< /代码>,以及一个结构<代码> MyIsAccess < /Cord>。如果x
是variant
的实例,则boost::apply_visitor(my_visitor(),x)
将根据变量中存储的类型调用访问者的相应操作符()。现在,如果你有一个std::vector
,你可以对每个元素使用apply\u visitor
。老实说,这是难以置信的。关于向量的某些元素,在编译时没有类型信息,因为这是运行时结构。它将如何推断正确的过载?。。或者我应该只看一下boost::variant
?:)的实现吗是的,这是运行时检测。Variant内部保存一个索引,指示存储的类型。您可以将Apple Yuto访问者视为一个交换机(index),其中每一种情况都调用正确的重载方法。我实际上不打算在这个特殊的问题中使用它,但我认为在其他情况下可以方便地利用它。
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]);
...
}
std::vector<std::pair< Type, boost::any > > data;