Context
I'm writing a math lib for training. Right now I'm working on the Matrix class. I'm trying to make a identityMatrix() function. This is a templated function that builds and returns a identity matrix. Right now my code is:
template<index_t N, typename Scalar = double> constexpr inline static const Matrix<N, N, Scalar> identityMatrix() noexcept { constexpr static Matrix<N, N, Scalar> id = [] { Matrix<N, N, Scalar> m(0); for (index_t i = 0; i < N; i++) { m.at(i, i) = static_cast<Scalar>(1.0); } return m; }(); return id; } I'm trying to make it so the matrix is build once only if needed, any later reference to the function returns a function local static const object. As the initialization is complex I'm using a lambda and calling it right away. The Matrix definition is as following:
using index_t = uint32_t; #define FOR(i, N) for(index_t i = 0; i < N; ++i) #define FORiN(N) FOR(i, N) template<index_t ROWS, index_t COLS = ROWS, typename Scalar = double> struct Matrix { static constexpr auto BUFFER_SIZE = ROWS * COLS; Scalar buffer[BUFFER_SIZE]; //... constexpr Matrix() noexcept = default; constexpr Matrix(const Scalar (&init_data)[BUFFER_SIZE]) noexcept { memcpy_s(buffer, BUFFER_SIZE * sizeof Scalar, &init_data , BUFFER_SIZE * sizeof Scalar); } constexpr Matrix(const std::initializer_list<std::initializer_list<Scalar>>& init_data) { static_assert(init_data.size() == ROWS && init_data.begin()->size() == COLS); FOR(row_index, ROWS) { Scalar* src_row = &init_data.begin()[row_index]; Scalar* dst_row = &buffer[row_index * COLS]; constexpr index_t row_size_bytes = COLS * sizeof Scalar; memcpy_s(dst_row, row_size_bytes, src_row, row_size_bytes); } } constexpr Matrix(Scalar homogenuos_value) noexcept { std::fill_n(buffer, BUFFER_SIZE, homogenuos_value); } constexpr Matrix(const Matrix& rhs) noexcept { FOR(i, BUFFER_SIZE) buffer[i] = rhs.buffer[i]; } inline constexpr static index_t indexOf(index_t col, index_t row) { return row * COLS + col; } inline constexpr Scalar& at(index_t row, index_t col) { return buffer[indexOf(row, col)]; } inline constexpr const Scalar& at(index_t row, index_t col) const { return buffer[indexOf(row, col)]; } //... more operators and stuff }; The problem
The test code i'm writting to test my matrix code is as following:
constexpr auto id = identityMatrix<3>(); constexpr auto manual_id = Matrix<3, 3>({ 1.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 1.0 }); static_assert(id == manual_id); print(id); Visual Studio gives me this:
And also:
Why
Why is this not working? I have make everything constexpr this should be constant at compile time. The compiler should be able to make this. What am I missing? What am I doing wrong?
Enviroment
I'm using
Microsoft Visual Studio Professional 2019 - version 16.4.2
Platform toolset: Visual Studio 2019 (v142)
C++ Language Standard: Preview - Features from the Latest C++ Working Draft (std:c++latest)
Today's date: 9 june 2020
