2015-06-20 51 views
2

我做了一个通用的n维数组类,但是我想通过一些编译时检查使它更安全。编译时间检查可变参数模板中参数的数量

构造函数和operator()只有当给定的参数个数等于dimension时才能正常工作。不过,如果我写这样

Array<int, 2> a(1, 2, 3); //3 dimensions for a 2d array == crash 

Array<int> a(1); //plain 1D array 
std::cout << a(1, 2); //segfault 

它只是默默地编译代码,我需要运行一个调试器,但它是相当混乱调试可变参数模板。

你能想到一个好的方法来提供一个编译时间检查匹配维度的正确数量的参数吗?

template<typename T, int dimension = 1> 
class Array 
{ 
private: 
    std::unique_ptr<T[]> pointer; 
    int size[dimension]; 
    int realSize; 

public: 
    Array() 
    { 
    } 

    template<typename... Ns> 
    Array(Ns... ns) 
    : realSize(1) 
    { 
     create(1, ns...); 
    } 

private: 
    template<typename... Ns> 
    void create(int d, int n, Ns... ns) 
    { 
     realSize *= n; 
     size[d - 1] = n; 
     create(d + 1, ns...); 
    } 

    void create(int d) 
    { 
     pointer = std::unique_ptr<T[]>(new T[realSize]); 
    } 

    int computeSubSize(int d) const 
    { 
     if (d == dimension) 
     { 
      return 1; 
     } 
     return size[d] * computeSubSize(d + 1); 
    } 

    template<typename... Ns> 
    int getIndex(int d, int n, Ns... ns) const 
    { 
     return n * computeSubSize(d) + getIndex(d + 1, ns...); 
    } 

    int getIndex(int d) const 
    { 
     return 0; 
    } 

public: 
    template<typename... Ns> 
    T& operator()(Ns... ns) const 
    { 
     return pointer[getIndex(1, ns...)]; 
    } 

    int getSize(int d = 1) const 
    { 
     return size[d - 1]; 
    } 
}; 
+0

'static_assert'或SFINAE可能会有帮助。 – Jarod42

回答

2

您可以添加编译时间在正确的地方断言语句,以防止类似

Array<int, 2> a1(1, 2, 3); 

Array<int> a3(1); 
std::cout << a3(1, 2); 

代码编译。

这里是曾经的地方:

template<typename... Ns> 
    Array(Ns... ns) 
    : realSize(1) 
    { 
     static_assert(sizeof ...(Ns) == dimension, "Incorrect number of arguments"); 
     create(1, ns...); 
    } 

,防止线路

Array<int, 2> a1(1, 2, 3); 

被编译。

另一个地方:

template<typename... Ns> 
    T& operator()(Ns... ns) const 
    { 
     static_assert(sizeof ...(Ns) == dimension, "Incorrect number of arguments"); 
     return pointer[getIndex(1, ns...)]; 
    } 

防止

Array<int> a3(1); 
std::cout << a3(1, 2); 

被编译。

这里有一些有效的语句:

Array<int, 2> a2(1, 2); 

Array<int> a3(1); 
std::cout << a3(0); 
相关问题