class — Перегрузка операторов в C ++ шаблонными классами

У меня есть следующий шаблон класса:

    template <class T>
class Matrix {

public:
Matrix(size_t rows, size_t columns, const T elements = 0);// scalar multiplication
Matrix<T> operator*(const T& rhs){

Matrix<T> result(rows, columns);

for(size_t index = 0; index < rows * columns; ++index){
result.elements[index] = elements[index] * rhs;
}

return result;
}

Matrix <T> operator*(const T& lhs, const Matrix<T>& rhs);const size_t rows;
const size_t columns;private:

std::vector<T> elements;
};

и следующая реализация оператора *:

// scalar multiplication
template <class T>
Matrix<T> Matrix<T>::operator*(const T& lhs, const Matrix<T>& rhs){

Matrix<T> result(rhs.rows, rhs.columns);

for(size_t index = 0; index < rhs.rows * rhs.columns; ++index){
result.elements[index] = elements[index] * lhs;
}
return result;
}

когда я пытаюсь собрать Clang говорит: error: overloaded 'operator*' must be a unary or binary operator (has 3 parameters)|

И я не совсем понимаю, чего мне в этом не хватает. В общем, классы шаблонов доставляют мне трудности, когда дело доходит до перегрузки операторов, и я не знаю почему. Здесь, на SO, было несколько сообщений на эту тему, и я попробовал несколько вариантов кода, но ни один из них не работал.

2

Решение

Простой и достаточно эффективный способ решения этой проблемы заключается в следующем:

  1. Воплощать в жизнь Matrix& operator *=(SomeType const&) и аналогичные операции в первую очередь. Это мутирует операции, которые изменяют экземпляр класса, а затем возвращают ссылку на *this,

  2. Реализуйте другие операции как действующие друзья с точки зрения *=где аргумент lhs (обычно) принимается по значению, изменяется и возвращается.

Это, как правило, очень просто и часто более эффективно, чем начинать с operator* вместо operator*=,

Итак, вы будете иметь:

 template<class T, etc>
struct Matrix{
Matrix& operator*=(T const&);
Matrix& operator*=(Matrix const&);
Matrix& operator+=(Matrix const&);

который вы реализуете традиционно. Затем:

   friend Matrix operator*(T const& t, Matrix m){ m*=t; return m; }
friend Matrix operator*(Matrix m, T const& t){ m*=t; return m; }

friend Matrix operator*(Matrix lhs, Matrix const& rhs){ lhs*=rhs; return lhs; }
friend Matrix operator+(Matrix lhs, Matrix const& rhs){ lhs+=rhs; return lhs; }

и теперь вам нужно всего лишь реализовать несколько традиционных методов.

Эти friend операторы являются встроенными не шаблонными встроенными функциями, которые генерируются автоматически для каждого экземпляра шаблона Matrix.

Ваша непосредственная проблема заключалась в том, что ваш нестатический оператор фактически принял неявный this в дополнение к его двум явным параметрам, и бинарные операторы не могут принимать 3 аргумента.


Сложное и даже более эффективное решение включает технику, часто называемую «шаблоны выражений». Недостатком является то, что шаблоны выражений более сложны для написания и имеют несколько точек хрупкости по всему auto Ключевое слово и подобные ситуации.

В качестве примера:

Matrix m = m1 * m2 + m3 * m4 + m5 + m6;

Выражение шаблон будет делать выше только с одним распределением внутренних данных матрицы.

Мой код выше скопирует m1, умножьте результат на m2, Тогда это будет копировать m3затем умножьте это на m4, Тогда он будет складывать все, не делая дополнительных копий. Наконец, этот результат будет перенесен в m,

Таким образом, две матрицы будут созданы вместо 1 в случае шаблона выражения.

Более наивное решение (например, дизайн ОП) создаст 5 матриц вместо 2.

3

Другие решения

Вы декларируете Matrix <T> operator*(const T& lhs, const Matrix<T>& rhs); как функция-член, которая имеет неявный параметр thisВот почему компилятор жалуется, что «имеет 3 параметра».

Вы можете сделать это бесплатной функцией шаблона,

template <class T>
class Matrix {
...
template <class Z>
friend Matrix<Z> operator*(const Z& lhs, const Matrix<Z>& rhs);
...
};

а также

// scalar multiplication
template <class Z>
Matrix<Z> operator*(const Z& lhs, const Matrix<Z>& rhs){

Matrix<Z> result(rhs.rows, rhs.columns);

for(size_t index = 0; index < rhs.rows * rhs.columns; ++index){
result.elements[index] = elements[index] * lhs;
}
return result;
}
2

Ваша функция является функцией-членом. Функции-члены имеют скрытый параметр, указатель this.

Вы должны либо сделать свой оператор * не являющейся членом функции, либо вам нужно избавиться от одного из аргументов функции вашего оператора * (которая затем умножит данные в «this» на данные во входящей матрице<T>.)

2
По вопросам рекламы [email protected]