简体   繁体   中英

How to initialize a 2D C-style array from a nested std::initializer_list?

I am creating a Matrix<type, width, height> class which I want to be able to initialize using initializer_list , for instance:

Matrix<int, 2, 2> mat = Matrix<int, 2, 2>{ {1,2},{3,4} };

The matrix is implemented using a T[height][width] 2D array.

To do this, I have tried making a constructor such as:

Matrix(std::initializer_list< std::initializer_list<T>> input);

However, I do not know how to fill the array with from the list. I have tried

  • using memcpy (corrupted memory),

  • std::copy (seems it is not possible to copy from an std::initializer_list ),

  • as well as used the assignment operator and () constructor call (but 2D arrays are not assignable and () constructor call does not compile).

Is there any other way, preferably as safe as possible, to do this?

You should provide exact type to the Matrix(std::initializer_list</* here */> list); . Then to fill the array, you need to iterate through the list passed and fill the array. ( See live online )

#include <initializer_list> // std::initializer_list

template<typename T, std::size_t R, std::size_t C>
class Matrix
{
    T mArray2D[R][C]{};

public:
    Matrix(const std::initializer_list<T[C]> list)
    //                                 ^^^^^ --> type of the row
    {
        auto iter{ list.begin() }; // returns pointer to T[C]
        for (std::size_t row{}; row < R; ++row)
        {
            const auto& rowElements{ *iter };
            for (std::size_t col{}; col < C; ++col)
            {
                mArray2D[row][col] = rowElements[col];
            }
            ++iter;
        }
    }
};

Now in the main() you can initialize Matrix using an initializer list as follows:

Matrix<int, 2, 2> mat{ {1,2}, {3,4} };
// or
// Matrix<int, 2, 2> mat = { {1,2}, {3,4} };

If you could use std::array , you could do the following. ( See live online )

#include <iostream>
#include <array>            // std::array
#include <initializer_list> // std::initializer_list

template<typename T, std::size_t R, std::size_t C>
class Matrix
{
    using RowType = std::array<T, C>;
    T mArray2D[R][C]{};

public:
    Matrix(const std::initializer_list<RowType> list)
    {
        auto iter{ list.begin() };
        for (std::size_t row{}; row < R; ++row)
        {
            const RowType& rowElements{ *iter };
            for (std::size_t col{}; col < C; ++col)
            {
                mArray2D[row][col] = rowElements[col];
            }
            ++iter;
        }
    }
};

If the multidimensional array in the class could be an std::array of std::array of type T , you could use std::copy as well. ( See live online )

#include <iostream>
#include <array>            // std::array
#include <initializer_list> // std::initializer_list
#include <algorithm>        // std::copy

template<typename T, std::size_t R, std::size_t C>
class Matrix
{
    using RowType = std::array<T, C>;
    using Array2D = std::array<RowType, R>;
    Array2D mArray{ RowType{} }; // initialize the matrix

public:
    Matrix(const std::initializer_list<RowType> list)
    {
       std::copy(list.begin(), list.end(), mArray.begin());
    }
};

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM