编译时间检查可变参数模板中的参数数量

时间:2015-06-20 04:36:18

标签: c++

我制作了一个通用的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];
    }
};

1 个答案:

答案 0 :(得分: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);