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

时间:2013-06-23 18:44:09

标签: c++ arrays templates

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

6 个答案:

答案 0 :(得分:2)

不,模板无法帮助您解决使用void*创建的问题。类型信息消失了。编译器只知道void*,并且不了解其背后组件的大小。

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

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

答案 1 :(得分:0)

为什么不使用模板库而不是编写自己的模板?

Boost::VariantBoost::Any可能会对您有所帮助。它们专门针对您遇到的问题而设计。

请参阅:boost::variant conversion to type

答案 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)

回答更新的问题:

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