qarabala
qarabala

Reputation: 178

Array-style initialisation of the matrix class

Suppose I want to create a matrix class in C++ which can be initialised using the curly brackets:

matrix<int> M = {{1,2,3}, {2,3,1}}

As I found out, the right hand side is an std::initializer_list object. I tried to implement the following:

template <typename ring>
class matrix {
private:
  std::vector<std::vector<ring>> vals;
public:
  matrix<ring>& operator=(const std::initializer_list<std::initializer_list<ring>>& rhs);
};

template<typename ring>
matrix<ring>& matrix<ring>::operator=(const std::initializer_list<std::initializer_list<ring>>& rhs) {
  unsigned new_rows = rhs.size();
  unsigned new_cols = 0;
  for (unsigned i=0; i<new_rows; ++i) if (new_cols < rhs[i].size()) new_cols = rhs[i].size();
  vals.resize(new_rows);
  for (unsigned i=0; i<vals.size(); ++i) {
    vals[i].resize(new_cols);
    for (unsigned j=0; j<new_cols; ++j) {
      vals[i][j] = rhs[i][j];
    }
  }
  return *this;
}

This does not work, and I get keeping the error message that rhs cannot accept the rhs[i][j] implementation. What am I doing wrong?

Upvotes: 1

Views: 67

Answers (1)

Caleth
Caleth

Reputation: 62684

matrix<double> M = {{1,2,3}, {2,3,1}}

Is copy-list-initialisation. You need a constructor

matrix<ring>(std::initializer_list<std::initializer_list<ring>> rhs) : vals(rhs.begin(), rhs.end()) {}

I'd retain the assignment operator, but implement it using the constructor

matrix<ring>& matrix<ring>::operator=(std::initializer_list<std::initializer_list<ring>> rhs) {
    matrix temp = rhs;
    std::swap(vals, temp.vals);
    return *this;
}

Aside: std::initializer_list is already a type with const reference semantics, you may as well take it by value.

Upvotes: 2

Related Questions