Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to initialize a matrix ONCE in a constexpr constructor?

Tags:

c++

c++20

I have the following matrix class:

template<size_t Rows, size_t Cols>
class matrix
{
    float data[Rows][Cols];
public:
    constexpr matrix(const float (&input)[Rows][Cols]) : data{}
    {
        for (size_t i = 0; i < Rows; ++i)
            std::copy(input[i], input[i] + Cols, data[i]);
    }
};

Usage:

constexpr auto m = matrix({
    {4.3f, 5.0f, 1.2f},
    {8.0f, 1.9f, 6.5f},
    {9.1f, 2.2f, 3.7f},
});

This compiles (in C++20) and works fine, but it requires initializing data twice. The first, data{}, is required because everything must be member-initialized in a constexpr constructor, and the second copies the actual input.

Initializing twice at compile time doesn't matter, but it also means this constructor can't be used at run-time since it needlessly initializes the same data twice.

Is there anything equivalent to this pseudo code?

constexpr matrix(const float (&input)[Rows][Cols])
{
    for (size_t i = 0; i < Rows; ++i)
        std::constexpr_uninitialized_copy(input[i], input[i] + Cols, data[i]);
}
like image 316
seaplusplus Avatar asked Sep 05 '19 14:09

seaplusplus


1 Answers

P1331 (Permitting trivial default initialization in constexpr contexts) was adopted for C++20. It removes the requirement that:

every non-variant non-static data member and base class subobject shall be initialized

which is what required you to have the : data {} initialization.

This should just work:

template<size_t Rows, size_t Cols>
class matrix
{
    float data[Rows][Cols];
public:
    constexpr matrix(const float (&input)[Rows][Cols])
    {
        for (size_t i = 0; i < Rows; ++i)
            std::copy(input[i], input[i] + Cols, data[i]);
    }
};

No need to initialize data anymore.

like image 114
Barry Avatar answered Nov 15 '22 04:11

Barry