C ++ Защищенный доступ член шаблонной структуры с различными значениями параметров шаблона - PullRequest
0 голосов
/ 28 мая 2018

Я создаю матричную функцию умножения, в которой возвращаемая матрица имеет размер, отличный от левой матрицы.В этой функции мне нужно получить доступ к защищенному члену матрицы, которую нужно вернуть, но я получаю ошибку компилятора C2248: не могу получить доступ к защищенному члену.Я полагаю, что это происходит потому, что аргументы шаблона имеют разные размеры.

template<typename T, std::size_t r, std::size_t c>
struct Matrix
{
  template<std::size_t c2>
  Matrix<T, r, c2> operator*(const Matrix<T, c, c2>& rhs);
protected:
  int test;
};

template<typename T, std::size_t r, std::size_t c>
template<std::size_t c2>
Matrix<T, r, c2> Matrix<T, r, c>::operator*(const Matrix<T, c, c2>& rhs)
{
  Matrix<T, r, c2> retMat;
  retMat.test;
  return retMat;
}

Я пытался найти функцию умножения operator*():

...
protected:
  int test;
  template<std::size_t c2>
  friend Matrix<T, r, c> Matrix<T, r, c2>::operator*(const Matrix<T, c2, c>& rhs);
};

, но я получаю:

error C2245: non-existent member function Matrix<T,r,c>::operator * specified as friend (member function signature does not match any overload)

Как получить доступ к защищенной переменной в Matrix с аргументами параметров шаблона другого размера?

Ответы [ 2 ]

0 голосов
/ 28 мая 2018

не может получить доступ к защищенному участнику.Я полагаю, что это происходит потому, что аргументы шаблона имеют разные размеры.

Точно: 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>>{}, "!" );
 }
0 голосов
/ 28 мая 2018

Речь идет не о «размере», а о матрицах разных типов.

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

Кроме того, вы не можете использовать друга, потому что не знаете (заранее) количество столбцов второй матрицы.

Способ перехода, IMO, это сделать члена доступным через аксессор.

Удачи!

Обновление:

Посмотрите на сигнатуру этой функции:

Matrix<T, r, c2> Matrix<T, r, c>::operator*(const Matrix<T, c, c2>& rhs)

Тип Matrix<T, c, c2> отличается от типа Matrix<T, r, c>, и оба они также отличаются от возвращаемого типа Matrix<T, r, c2>.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...