c++matrixconstructorinitializer-listtemplate-classes

How to create a initializer list constructor using a custom template subclass?


Basically, what I wanna do is be able to construct an object using a list of primitives like this:

int main()
{
  // C primitives initialization list
  int matrix[2][2] = { { 1, 2 }, { 2, 3 }, };

  // C++ stl class initialization list
  std::string s = { 'f', 'o', 'o' '\0' };

  // My custom 2x2 Matrix subclass
  Matrix2<int> mat = { { 2, 0 }, { 6, 7 } }; // is it possible?
}

I've tried using the declaration inspired in this thread but it was not successful

constexpr initializer_list() noexcept : _First(nullptr), _Last(nullptr) {}

template <class T, unsigned int M, unsigned int N> class Matrix {
  
  // Matrix(initializer_list<T> &&lst) : _First(nullptr), _Last(nullptr) {} // (1) Does not work
  Matrix(std::initializer_list<T> &&lst) { } // (2) no error on definition itself

}

template <class T> class Matrix2 : public SquareMatrix<T, 2> {};

(1): Does not work due to the clang error above: clang: Member initializer '_First' does not name a non-static data member or base class [mem_init_not_member_or_class]

(2): Also don't work due to the error upon construction of Matrix and Matrix2:

I've omitted major code to simplify the question, full code can be found here


Solution

  • You may code it as std::initializer_list<std::initializer_list<T>>:

    template<typename T>
    class Matrix2
    {
    public:
        Matrix2(std::initializer_list<std::initializer_list<T>> list) {
            if (list.size() > 2)
                throw std::out_of_range{ "Too many rows." };
    
            int rowNum = 0;
            for (auto& row : list)
            {
                if(row.size() > 2)
                    throw std::out_of_range{ "Too many cols." };
    
                int colNum = 0;
                for (auto& ele : row)
                    mat[rowNum][colNum++] = ele;
                rowNum++;
            }
            // for debug
            for (int i = 0; i < 2; i++)
                for (int j = 0; j < 2; j++)
                    std::cout << mat[i][j];
        }
    private:
        T mat[2][2];
    };
    
    int main()
    {
        Matrix2 mat{ {1, 2}, {3, 4} };
        return 0;
    }