Можно ли изменить аргументы шаблонов? - PullRequest
0 голосов
/ 14 ноября 2018

Я написал следующий класс Matrix:

template <typename T, size_t r, size_t c> //r=rows,c=cols of the Matrix
class Matrix {
public:
    size_t row = 0;
    size_t col = 0;
    T *data;

    template <size_t L>
    Matrix<T, r, L> operator*(const Matrix<T, c, L> &other) const;

    template <size_t r, size_t c>
    Matrix &operator=(const Matrix<T, r, c> &other)

    // ...
};

Я переопределил некоторые операторы, чтобы выполнить некоторую основную арифметику, и, кажется, все работает правильно - однако есть проблема, которую я не знаю, как правильно ее решить: учитывая следующие строки кода:

  Matrix<double, 1, 4> m1(1.2);
  Matrix<double, 4, 1> m2(1.2);
  Matrix<double, 2, 2> m3; // problematic line
  m3 = m1 * m2;

m3 относится к типу Matrix<double, 2, 2>, правильно вычислен, имеет одну строку и один столбец и содержит 5.76, но остается как Matrix<double, 2, 2>. Изменение количества строк и столбцов не отражается в параметрах шаблона. Естественно, однако, я ожидал бы, что тип будет также информативным относительно его содержания.

Я не думаю, что никто не может внезапно превратить Matrix<double, 2, 2> в матрицу Matrix<double, 1, 1>, но, возможно, есть хорошее решение, о котором я сейчас не могу думать.

И заменить:

 template <size_t r, size_t c> void replace(const Matrix<T, r, c> &other) {
    delete[] data; 
    row = other.row; //number of rows of a matrix
    col = other.col; //number of cols of a matrix
    data = new T[col * row]; // data contains all the elements of my matrix
    for (size_t i = 0; i < row * col; i++)
      data[i] = other.data[i];
  }

1 Ответ

0 голосов
/ 14 ноября 2018

Из вашей декларации

template <typename T, size_t r, size_t c> //r=rows,c=cols of the Matrix
class Matrix {
public:
    template <size_t L>
    Matrix<T, r, L> operator*(const Matrix<T, c, L> &other) const;

    template <size_t r, size_t c> // BEWARE: shadowing
    Matrix &operator=(const Matrix<T, r, c> &other);

    // ...
};

мы можем догадаться, что произойдет.

Matrix<double, 1, 4> m1(1.2);
Matrix<double, 4, 1> m2(1.2);
m1 * m2; // (1)

(1) звонит Matrix<double, 1, 4>::operator*<1>(Matrix<double, 4, 1> const&).В результате он имеет тип Matrix<double, 1, 1>.

Matrix<double, 2, 2> m3;
m3 = /* (2) */ m1 * m2;

(2) звонки Matrix<double, 2, 2>::operator=<1, 1>(Matrix<double, 1, 1> const&).Это проблема.

Решение состоит в том, чтобы operator= можно было вызывать только с другой матрицей вправо размера:

template <typename T, size_t r, size_t c> //r=rows,c=cols of the Matrix
class Matrix {
public:
    template <size_t L>
    Matrix<T, r, L> operator*(Matrix<T, c, L> const& other) const;

    Matrix &operator=(Matrix const& other);

    // ...
};

Вы могли бы дажеразрешить преобразования типов:

template<class U>
Matrix &operator=(Matrix<U, r, c> const& other);

Наконец, вы можете использовать auto:

Matrix<double, 1, 4> m1(1.2);
Matrix<double, 4, 1> m2(1.2);
auto m3 = m1 * m2; // m3 is Matrix<double, 1, 1>
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...