1

如何使用 C++ 模板来完成以下任务,或者有更好的方法吗?

我的 pgm 包含许多大而简单的表。为了节省空间,每个表可以是 char、short、long 或 long long(即,在我的编译器 VS2010 中具有 8、16、32 或 64 位的条目),具体取决于表的内容(表在开始时构建一次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
    ...
4

6 回答 6

2

不,模板无助于解决您使用void*. 类型信息消失了。编译器只知道void*它后面的组件的大小,并且对它的大小知之甚少。

另一方面,如果您一开始就使用模板,则不会遇到此问题:

template < typename T >
struct V { int n; T * v; };
于 2013-06-23T18:47:13.533 回答
0

要回答更新的问题:

  1. 您使用开关:
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>

于 2013-06-25T08:09:17.373 回答
0

与其编写自己的模板,不如使用模板库?

Boost::VariantBoost::Any可能会在这里对您有所帮助。它们专为您遇到的那种问题而设计。

请参阅:boost::variant 转换为类型

于 2013-06-23T18:49:25.843 回答
0

如果我正确理解了您的要求,您可能需要查看向量库。例如:

#include <vector>

std::vector<char> V;

V 现在是一个动态列表,每个元素的宽度为 1 个字符。

于 2013-06-23T20:42:03.323 回答
0

也许你会通过编写一个“原始”容器来成为更好的服务器......(甚至使用标准容器。)
如果你自己编写,std::array 的设计是你应该寻求复制的,除非你需要大小是动态的。

template<typename T, std::size_t N>
class array
{
public:
    //....Constructors..etc
private:
    T* data;
}

另外,考虑实现迭代器,听起来你的很多功能会更简单地实现。

于 2013-06-23T20:15:03.647 回答
-1

你可以做的是使用联合。

做这样的事情

union unionType {
  char a;
  int b;
  long long c;
};

现在这将允许您将数组类型指定为联合。这样做的问题是,由于联合插入的填充,您可能会浪费大量内存。您可能还必须执行类似的操作来跟踪类型:

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

于 2013-06-23T18:52:04.603 回答