如何使用C ++模板完成以下操作,还是有更好的方法?
我的pgm包含许多大而简单的表格。为了节省空间,每个表可以是char,short,long或long long(即我的编译器中的8,16,32或64位条目,VS2010),具体取决于表的内容(表格在开头构建一次(pgm)。我有在这些表上运行的函数,我想编写一个处理所有类型的函数。
使用new分配表。用于说明的简化版本:
struct S1 {char x;}
struct S2 {short x;};
struct S4 {long x;}
struct S8 {long long x;};
struct V {int n; void *v}; // n=1,2,4 or 8, and v points to an array of Sn
V.v=new Sn[arrayLength]; // Sn is one of S1, S2, S4 or S8
当我想使用v [i]访问数组元素时出现问题,因为数组元素大小在编译时是未知的。似乎模板应该允许这样做,但我没有经验。
详细说明,结合Crazy Eddie的建议,我的代码现在看起来像
在VA.h中:
class VA
{
struct S1 {char x;}
struct S2 {short x;};
struct S4 {long x;}
struct S8 {long long x;};
template < typename T>
struct V {int n; T *v}; // n=1,2,4 or 8, and v points to an array of Sn
V vTable[1000]; // a fixed array size
void Func1(int k, int n, int size);
};
在VA.cpp中:
void Func1(int k, int n, int size)
{
V<T> *pV=&vTable[k]; // Question 1: How do I get from n to the appropriate type T?
pV->n=n;
pV->v=new SOMETHING[size]; // Question 2: What should SOMETHING be here?
// I am allocating an array of Sn
...
答案 0 :(得分:2)
不,模板无法帮助您解决使用void*
创建的问题。类型信息消失了。编译器只知道void*
,并且不了解其背后组件的大小。
另一方面,如果您使用模板开头,则不会遇到此问题:
template < typename T >
struct V { int n; T * v; };
答案 1 :(得分:0)
为什么不使用模板库而不是编写自己的模板?
Boost::Variant或Boost::Any可能会对您有所帮助。它们专门针对您遇到的问题而设计。
答案 2 :(得分:0)
也许你会通过写一个'原始'容器来改善服务器......(甚至使用标准容器。)
如果自己编写,std :: array的设计是你应该寻求复制的,除非你需要大小是动态的。
template<typename T, std::size_t N>
class array
{
public:
//....Constructors..etc
private:
T* data;
}
另外,考虑实现迭代器,听起来很多函数会更容易实现。
答案 3 :(得分:0)
如果我理解了您的要求,您可能需要查看矢量库。 E.g:
#include <vector>
std::vector<char> V;
V现在是一个动态列表,其元素各为1个字符宽。
答案 4 :(得分:0)
回答更新的问题:
template<typename Sn> void Func1(int k, int size) { V<Sn> *pV=&vTable<Sn>[k]; // No need for pv->n; just call sizeof(T). pV->v=new Sn[size]; } void Func1(int k, int n, int size) { switch (n) { case 1: Func1<S1>(k, size); case 2: Func1<S2>(k, size); // ... } }
请注意,当您在编译时知道n
时,可以直接调用Func1。也,
请注意V
是一个类模板,而不是一个类。 V<S1>
是一个班级。因此,您不能拥有V
的数组,但是您可以拥有V<S1>
数组。
答案 5 :(得分:-1)
你可以做的是使用联盟。
做同样的事情
union unionType {
char a;
int b;
long long c;
};
现在,这将允许您将数组类型指定为union。这个问题是你可能会因为工会插入的填充而浪费一堆浪费的内存。您可能还需要执行类似操作以跟踪类型:
struct arrayType {
int type; //Something like 0-char, 1-short, 2-long, etc...
unionType value;
};
struct arrayType {
int length;
arrayType v;
}
有关工会的更多信息,我实际上非常喜欢它们上的维基百科页面:http://en.wikipedia.org/wiki/Union_type