c ++编译时检查函数参数

时间:2013-09-24 12:33:46

标签: c++

如果可以为编译器做的话,我正在寻找一种在编译时检查函数参数的方法。

更具体一点: 假设我们有一些类Matrix。

class Matrix
{
    int x_size;
    int y_size;

public:
    Matrix(int width, int height):
        x_size{width},
        y_size{height}
    {}
    Matrix():
        Matrix(0, 0)
    {}
};

int main()
{
    Matrix a; // good.
    Matrix b(1, 10); // good.
    Matrix c(0, 4); // bad, I want compilation error here.
}

那么,在传递给函数的静态(源编码)值的情况下,是否可以检查或区分行为(函数重载?)?

如果值不是静态的:

std::cin >> size;
Matrix d(size, size);

我们只能进行运行时检查。但是如果值在源代码中编码?在这种情况下我可以进行编译时检查吗?

编辑:我认为constexpr constructor可以实现这一点,但无论如何都不允许使用和不使用constexpr进行重载。所以问题无法以我想象的方式解决。

4 个答案:

答案 0 :(得分:5)

要获得编译时错误,您需要一个模板:

template <int width, int height>
class MatrixTemplate : public Matrix
{
    static_assert(0 < width, "Invalid Width");
    static_assert(0 < height, "Invalid Height");
    public:
    MatrixTemplate()
    : Matrix(width, height)
    {}
};

(顺便说一句:我建议索引的无符号类型)

如果你没有static_assert(这里我切换到unsigned):

template <unsigned width, unsigned height>
class MatrixTemplate : public Matrix
{
    public:
    MatrixTemplate()
    : Matrix(width, height)
    {}
};

template <> class MatrixTemplate<0, 0> {};
template <unsigned height> class MatrixTemplate<0, height> {};   
template <unsigned width> class MatrixTemplate<width, 0> {};

此处不支持空矩阵(MatrixTemplate&lt; 0,0&gt;)。但是调整static_asserts或类MatrixTemplate&lt; 0应该是一件容易的事。 0 GT;

答案 1 :(得分:3)

您可以添加如下方法:

template <int WIDTH, int HEIGHT>
Matrix CreateMatrix()
{
    static_assert(WIDTH > 0, "WIDTH > 0 failed");
    static_assert(HEIGHT > 0, "HEIGHT > 0 failed");

    return Matrix(WIDTH, HEIGHT);
}

int main() {
    Matrix m(0, 2);     // no static check
    Matrix m2 = CreateMatrix<0,2>(); // static check

    return 0;
}

答案 2 :(得分:1)

线性代数包倾向于这样做的方法是使用固定大小矩阵的模板,如:

template<int x, int y> class Matrix { ... }

和一个可以在运行时改变大小的矩阵的额外类

class DynamicMatrix {...}

当他们想要固定大小的矩阵时,您仍然必须依赖程序员实际使用第一个选项,但是当xy为零时,模板版本可以很容易地生成编译器错误。

答案 3 :(得分:0)

运行时:

Matrix(int width, int height):
    x_size{width},
    y_size{height}
{
        assert(x_size>0);
        assert(y_size>0);
}

编译时(实际上你不能用函数参数做。你可以使用模板方式):

template <size_t WIDTH, size_t HEIGHT>
class Matrix
{
    const size_t x_size = WIDTH;
    const size_t y_size = HEIGHT;

    static_assert(WIDTH > 0, "Width must > 0");
    static_assert(HEIGHT > 0, "Height must > 0");
};