0

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:

  • clang: Too few template arguments for class template 'Matrix' [template_arg_list_different_arity]
  • clang: No viable conversion from 'int' to 'Matrix<int, 2, 2>' [typecheck_nonviable_condition]

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

Gerson
  • 3
  • 1

2 Answers2

1

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;
}
o_oTurtle
  • 1,091
  • 3
  • 12
  • **It worked!** Thank you! *but...* I still have to redefine the constructor on each subclass of `Matrix`. [Full code here](https://pastebin.com/vddr3RM2) for those interested. – Gerson Jul 30 '23 at 14:42
0

{..} has no type, it is not an std::initializer_list.

{..} forbids most deduction except std::initializer_list and C-array types.

std::initializer_list is most for "unknown" size.

for matrix2x2, C-array seems more appropriate (size might be checked at compile time):

template <typename T>
class Matrix2
{
public:
    Matrix2(const T (&ini)[2][2]) : mat{ini[0][0], ini[0][1], ini[1][0], ini[1][1]} {}
// ...
private:
    T mat[2][2];
};
Jarod42
  • 203,559
  • 14
  • 181
  • 302
  • One problem is that `mat` is a member of `Matrix` not `Matrix2` so I can't use member initialization list on constructor, must access using `this->` which is ok since I want to use it for MxN matrices on the super class `Matrix` anw. This works: ```C++ const int arr[2][2] = {{2, 0}, {6, 7}}; Matrix2 a = arr; ``` but this do not: `Matrix2 a = {{2, 0}, {6, 7}};` due to: `error: could not convert ‘{{2, 0}, {6, 7}}’ from ‘’ to ‘Matrix2’` – Gerson Jul 30 '23 at 14:03
  • Constructor are not inherited by default, you have to do it manually: [Demo](https://godbolt.org/z/f3GqqKG3a) most of your heritage might simply be `using`. and if you have access to C++20, no need of `SquaredMatrix` neither, a `requires (N == M)` for specific method would be enough. – Jarod42 Jul 30 '23 at 14:37
  • Thanks! I am using `C++ 13.1.1 (g++)` so `requires` is not available. [Here is the updated version (3)](https://pastebin.com/9SnBLfHe), with both c array and `initializer_list` constructors. – Gerson Jul 30 '23 at 17:04
  • For code, you might use godbold.org (or other online compiler) instead of pastebin.com, So you have syntax color, and compilation. – Jarod42 Jul 31 '23 at 09:42