C++模板访问不同元素大小的数组

C++ templates to access arrays of different element size?

本文关键字:数组 元素 访问 C++      更新时间:2023-10-16

如何使用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
    ...

不,模板不会帮助解决您使用void*创建的问题。类型信息不见了。编译器只知道void*,对它后面的组件的大小一无所知

另一方面,如果你一开始就使用模板,你就不会有这个问题:

template < typename T >
struct V { int n; T * v; };

与其编写自己的模板,为什么不使用模板库呢?

Boost::Variant或Boost::Any可能会对您有所帮助。它们是专门为你遇到的那种问题而设计的。

请参阅:boost::转换为类型的变体

也许编写一个"基元"容器会让您成为更好的服务器。。(甚至可以使用标准的。)
如果你自己写,std::array的设计是你应该复制的,除非你需要动态的大小。

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

此外,考虑实现迭代器,听起来你的很多函数都会更容易实现。

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

#include <vector>
std::vector<char> V;

V现在是一个动态列表,其元素每个都有1个字符宽。

要回答更新的问题:

  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>的数组。

您可以使用并集。

做一些类似的事情

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