не может получить доступ к защищенному участнику.Я полагаю, что это происходит потому, что аргументы шаблона имеют разные размеры.
Точно: Matrix<int, 2, 3>
отличается от (по примеру) Matrix<int, 3, 4>
;поэтому в методе Matrix<int, 2, 3>
вы не можете получить доступ к test
члену Matrix<int, 3, 4>
.
Я попытался найти функцию умножения operator*()
Это правильный путь, но вы забыли важный элемент: функция friend
не является методом класса;это нормальная функция.
Если вы реализуете operator*()
как метод класса (неправильный путь по многим причинам), ему нужен только явный параметр (операнд справа от *
), потому чтодругой элемент (операнд слева от *
) неявно является элементом *this
.
Но когда вы реализуете operator*()
как функцию (friend
для класса или нет),нет неявного элемента *this
;поэтому функция нуждается в двух параметрах.
Так что неправильно ваш
template<std::size_t c2>
friend Matrix<T, r, c> Matrix<T, r, c2>::operator*(const Matrix<T, c2, c>& rhs);
, потому что получает только параметр и не является Matrix<T, r, c2>::
.
Правильный способ решения этой проблемы (IMHO) - это функция (а не метод) следующим образом:
template <typename T, std::size_t D1, std::size_t D2, std::size_t D3>
Matrix<T, D1, D3> operator* (Matrix<T, D1, D2> const & m1,
Matrix<T, D2, D3> const & m2)
{
Matrix<T, D1, D3> retMat;
retMat.test = m1.test + m2.test;
return retMat;
}
, которая должна быть дружественной к Matrix<T, D1, D2>
, Matrix<T, D2, D3>
и Matrix<T, D1, D3>
.
Вы можете попытаться определить его внутри класса
template <typename T, std::size_t R, std::size_t C>
struct Matrix
{
protected:
T test;
template <typename U, std::size_t D1, std::size_t D2, std::size_t D3>
friend Matrix<U, D1, D3> operator* (Matrix<U, D1, D2> const & m1,
Matrix<U, D2, D3> const & m2)
{
Matrix<T, D1, D3> retMat;
retMat.test = m1.test + m2.test;
return retMat;
}
};
, но это неправильно, поскольку вызывает множественное определение одной и той же функции в разных классах.
Поэтому я предлагаю объявляют (но не определяют) operator*()
friend
внутри класса
template <typename T, std::size_t R, std::size_t C>
struct Matrix
{
protected:
T test;
template <typename U, std::size_t D1, std::size_t D2, std::size_t D3>
friend Matrix<U, D1, D3> operator* (Matrix<U, D1, D2> const & m1,
Matrix<U, D2, D3> const & m2);
};
и определяют его снаружи.
Следующееесли полный рабочий пример
#include <type_traits>
template <typename T, std::size_t R, std::size_t C>
struct Matrix
{
protected:
T test;
template <typename U, std::size_t D1, std::size_t D2, std::size_t D3>
friend Matrix<U, D1, D3> operator* (Matrix<U, D1, D2> const & m1,
Matrix<U, D2, D3> const & m2);
};
template <typename T, std::size_t D1, std::size_t D2, std::size_t D3>
Matrix<T, D1, D3> operator* (Matrix<T, D1, D2> const & m1,
Matrix<T, D2, D3> const & m2)
{
Matrix<T, D1, D3> retMat;
retMat.test = m1.test + m2.test;
return retMat;
}
int main ()
{
Matrix<long, 2U, 3U> a;
Matrix<long, 3U, 4U> b;
auto c { a * b };
static_assert( std::is_same<decltype(c), Matrix<long, 2U, 4U>>{}, "!" );
}