我正在创建模板化矩阵乘法函数,其中返回的矩阵的大小与左侧矩阵的大小不同。在该函数中,我需要访问要返回的矩阵的 protected 成员,但出现编译器错误C2248:无法访问 protected 成员。我相信这是因为模板参数的大小不同。

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*()乘法函数作为 friend :
...
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中的 protected 变量?

最佳答案



确实:Matrix<int, 2, 3>Matrix<int, 3, 4>是不同的类型(例如);因此,在Matrix<int, 2, 3>方法内部,您无法访问testMatrix<int, 3, 4>成员。



这是正确的方法,但是您忘记了一个重要的元素: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>的 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)
       {
         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>>{}, "!" );
 }

09-10 00:07
查看更多