模板类的成员函数参数
Parameter of member functions of template class
我正在尝试更好地理解模板,并转向好的'ole矩阵类。 我知道本征、犰狳等,我的目的是更好地理解模板。 我的问题是,如何让成员函数接受一个参数,该参数是同一模板类的对象,但具有不同的专用化?
例如,我尝试组合在一起的矩阵类需要两个模板参数 - 行数和列数。 此外,任何 m x n 矩阵对象 (Matrix<mRows,nCols>
) 应该能够取一个 n x p 矩阵对象 (Matrix<nCols,pCols>
) 并将它们相乘并返回一个 m x p 矩阵对象 (Matrix<mRows,pCols>
):
template <unsigned mRows, unsigned nCols>
class Matrix
{
private:
double matrixData[mRows][nCols];
//...other stuff
public:
//...other stuff
Matrix operator * (const Matrix<nCols, pCols>& rhs);
}
// simple naive matrix multiplication method
template <unsigned mRows, unsigned nCols>
Matrix<nCols,pCols> Matrix<mRows, nCols>::operator * (const Matrix<nCols,pCols>& rhs)
{
Matrix<nCols,pCols> temp();
for (int r = 0; r<mRows; ++r)
{
for(int c = 0;c<pCols;++c)
{
temp.matrixData[r][c]=0;
for (int elem = 0; elem<nCols;++elem)
{
temp.matrixData[r][c]+= matrixData[r][elem]*rhs.matrixData[elem][c];
}
}
}
return temp;
}
主要功能如下所示:
int main()
{
Matrix<2,3> m1;
Matrix<3,4> m2;
//...initialize matrices...
Matrix<2,4> m3 = m1 * m2;
}
这是行不通的,因为 pCols 没有在任何地方声明。应该在哪里/如何声明?
您必须使用函数模板定义中可用的模板参数来专门化 Matrix 类,在这种情况下:
template <unsigned mRows, unsigned nCols>
Matrix<mRows,nCols> Matrix<mRows, nCols>::operator * (const Matrix<nCols,mRows>& rhs)
然后,最好在声明和定义中对模板参数使用一致的命名约定。
将模板参数视为可在其后实体中使用的类型/常量。声明是定义在此上下文中本质上是单独的实体(这就是为什么您需要在提供函数定义时第二次键入 template<>)。
编辑:再次仔细阅读问题后,事实证明我的答案没有抓住重点。哥伦布的答案是要走的路。
operator*
自己做一个成员函数模板。 即写在类模板内
template <unsigned pCols>
Matrix operator * (const Matrix<nCols, pCols>& rhs);
和外面使用两个参数列表:
template <unsigned mRows, unsigned nCols>
template <unsigned pCols>
Matrix<mRows, pCols> Matrix<mRows, nCols>::operator * (const Matrix<nCols,pCols>& rhs)
但是,我鼓励您使用friend
非成员函数。
operator*
函数只需要一个模板参数。RHS 的行数必须与 LHS 的列数相同。
template <unsigned pCols>
Matrix<nRows, pCols> operator * (const Matrix<nCols, pCols>& rhs)
{
//...
}
在弄乱了一段时间之后,我终于有了使用哥伦布建议的解决方案。 第一种解决方案将乘法运算符保留为成员函数,然后使所有专业化彼此友好,以便它们可以修改彼此的私人数据:
template <unsigned mRows, unsigned nCols>
class Matrix
{
private:
double matrixData[mRows][nCols];
public:
template<unsigned nRows, unsigned pCols> // make all specializations of the templates friends with each other
friend class Matrix;
// ... constructor and other operator definitions/prototypes here
// define proper matrix multiplication
// should be defined such that Matrix<mRows,pCols> = Matrix<mRows,nCols>*Matrix<nCols*pCols>
// since the inner dimensions of the matrix must be the same.
template <unsigned pCols>
Matrix<mRows,pCols> operator * (const Matrix<nCols, pCols>& rhs) const;
};
template <unsigned mRows, unsigned nCols>
template <unsigned pCols>
Matrix<mRows,pCols> Matrix<mRows, nCols>::operator * (const Matrix<nCols,pCols>& rhs) const
{
Matrix<mRows,pCols> temp;
for (unsigned r = 0; r<mRows; ++r)
{
for(unsigned c = 0;c<pCols;++c)
{
temp.matrixData[r][c]=0;
for (unsigned elem = 0; elem<nCols;++elem)
{
temp.matrixData[r][c]+= matrixData[r][elem]*rhs.matrixData[elem][c];
}
}
}
return temp;
}
第二个解决方案遵循 Columbo 的建议,使乘法运算符成为friend
非成员函数:
template <unsigned mRows, unsigned nCols>
class Matrix
{
private:
double matrixData[mRows][nCols];
public:
// ... constructor and other operator definitions/prototypes here
// define proper matrix multiplication
// should be defined such that Matrix<mRows,pCols> = Matrix<mRows,nCols>*Matrix<nCols*pCols>
// since the inner dimensions of the matrix must be the same.
template <unsigned m, unsigned n, unsigned p>
friend Matrix<m,p> operator * (const Matrix<m,n>& lhs, const Matrix<n, p>& rhs);
};
template <unsigned m, unsigned n, unsigned p>
Matrix<m,p> operator * (const Matrix<m,n>& lhs, const Matrix<n, p>& rhs)
{
Matrix<m,p> temp;
for (unsigned r = 0; r<m; ++r)
{
for(unsigned c = 0;c<p;++c)
{
temp.matrixData[r][c]=0;
for (unsigned elem = 0; elem<n;++elem)
{
temp.matrixData[r][c]+= lhs.matrixData[r][elem]*rhs.matrixData[elem][c];
}
}
}
return temp;
}
如果有人能评论为什么一个比另一个更好,那就太好了。 我认为第二种解决方案更好,因为只有该函数专门用于不同的组合而不是整个类(对吧?例如,在Matrix<3,3> * Matrix<3,4>
与Matrix<3,3> * Matrix<3,5>
中,Matrix<3,3>
类只需要专门化一次,而* operator
类将专门涵盖这两种情况。右?
- static_assert在宏中,但也可以扩展到可以用作函数参数的东西
- C++中的高效循环缓冲区,它将被传递给C样式数组函数参数
- 当从函数参数中的临时值调用复制构造函数时
- 如何从"decltype()"获取函数参数的数量<funtion>?
- 如何将lambda作为模板类的成员函数参数
- 模板参数推导失败,函数参数/参数不匹配
- 如何在C++中将迭代器作为函数参数传递
- 将函数参数"const char*"转换为"std::string_view"是
- C++ 如何将数组值解压缩为函数参数
- 主函数参数的属性
- 具有两个间接寻址运算符 (C++) 的函数参数的用途
- "Warning: Comma within array index expression"但逗号分隔函数参数
- 如何定义在用作函数参数时工作的类模板的转换
- 将函数参数完美转发到函数指针:按值传递呢?
- 为什么我不能将引用作为 std::async 的函数参数传递
- 什么..(省略号)作为函数原型中唯一的函数参数,C++?
- 是否可以就地构造一个固定大小的数组作为函数参数?
- 接受模板作为函数参数
- 将成员函数作为构造函数参数调用时出错 "Variable is not a type name"
- Arduino 函数参数