Проблема в том, что operator*()
определяется внутри в шаблоне matrix
класс.
Итак, когда вы определяете объект matrix
, скажем matrix<double, 1, 2>
, эта функция определена; когда вы определяете другой объект с таким же типом и разными размерами, скажем, matrix<double, 2, 1>
, точно такая же функция шаблона переопределяется.
Мне кажется, что нет ничего, что требовало бы, чтобы эта функция была friend
из matrix
, поэтому - предложение - удалите ее внутри класса и переписайте ее снаружи, как показано ниже
template <class Type, std::size_t N>
using container = std::array<Type, N>;
using size_type = std::size_t;
template <typename value_type, std::size_t Rows_lhs, std::size_t Columns_lhs,
std::size_t Rows_rhs, std::size_t Columns_rhs>
constexpr matrix<value_type, Rows_lhs, Columns_rhs> operator*(
const matrix<value_type, Rows_lhs, Columns_lhs>& lhs,
const matrix<value_type, Rows_rhs, Columns_rhs>& rhs)
{
static_assert(Columns_lhs == Rows_rhs, "Incorrect matrix for product!");
matrix<value_type, Rows_lhs, Columns_rhs> result{};
container<value_type, Rows_rhs> thatColumn{};
for (size_type j = 0; j < Columns_rhs; ++j)
{
for (size_type k = 0; k < Rows_rhs; ++k)
{
thatColumn.at(k) = rhs(k, j);
}
for (size_type i = 0; i < Rows_lhs; ++i)
{
const auto thisRow = lhs(i);
value_type summand{};
for (size_type k = 0; k < Rows_rhs; ++k)
{
summand += thisRow.at(k) * thatColumn.at(k);
}
result(i, j) = summand;
}
}
return result;
}
Если вы действительно хотите, вы можете сохранить его friend
, но только объявив его внутри класса matrix
template <typename value_type, std::size_t Rows_lhs,
std::size_t Columns_lhs, std::size_t Rows_rhs,
std::size_t Columns_rhs>
friend constexpr matrix<value_type, Rows_lhs, Columns_rhs> operator*(
const matrix<value_type, Rows_lhs, Columns_lhs>& lhs,
const matrix<value_type, Rows_rhs, Columns_rhs>& rhs);
Бонус (не по теме): нет необходимости определять четыре размерности матрицы и накладывать с static_assert()
, что второе (Columns_lhs
) и третье (Rows_rsh
) равны .
Вы можете объединить их в один параметр шаблона (midDim
, в следующем примере)
template <typename value_type, std::size_t Rows_lhs, std::size_t midDim,
std::size_t Columns_rhs>
constexpr matrix<value_type, Rows_lhs, Columns_rhs> operator*(
const matrix<value_type, Rows_lhs, midDim>& lhs,
const matrix<value_type, midDim, Columns_rhs>& rhs)
{
matrix<value_type, Rows_lhs, Columns_rhs> result{};
container<value_type, midDim> thatColumn{};
for (size_type j = 0; j < Columns_rhs; ++j)
{
for (size_type k = 0; k < midDim; ++k)
{
thatColumn.at(k) = rhs(k, j);
}
for (size_type i = 0; i < Rows_lhs; ++i)
{
const auto thisRow = lhs(i);
value_type summand{};
for (size_type k = 0; k < midDim; ++k)
{
summand += thisRow.at(k) * thatColumn.at(k);
}
result(i, j) = summand;
}
}
return result;
}