C ++ compile-time checking function arguments

I am looking for a way to check function arguments at compile time, if possible for the compiler.

To be more specific: suppose we have some cool 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. } 

So, can I test or differentiate the behavior (function overload?) In the case of static (initial) values ​​passed to the function?

If the value is not static:

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

we can perform runtime checks. But if the values ​​are encoded in the source? Can I do a compile time check in this case?

EDIT: I think this is possible using the constexpr constructor , but in any case, overloading with and without constexpr is not allowed. Therefore, the problem cannot be solved in the way I believe.

+7
c ++
source share
4 answers

To get a compile-time error, you need a template:

 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) {} }; 

(Btw: I suggest unsigned types for indexes)

If you don't have static_assert (here I switch to 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> {}; 

There is no support for empty matrices (MatrixTemplate <0, 0>). But it should be a simple task to set up static_asserts or the MatrixTemplate <0. 0> class.

+4
source share

You can add a method like this:

 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
source share

The way linear algebra packages strive to do this is to use templates for fixed-size matrices, as in:

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

and an extra class for matrices that can resize at runtime

class DynamicMatrix {...}

You still have to rely on the programmer, using the first option, when they need fixed-size matrices, but the template version makes it easier to create compiler errors when x or y are zero.

+1
source share

at runtime:

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

Compilation time (in fact, you could not do this with function arguments. You can use template methods):

 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"); }; 
0
source share

All Articles