假设我有一个模板类,例如template<int n, int m> class Matrix
有没有办法定义矩阵乘法运算符*这样
我想到的是类似的东西
template< int n,int k, int m, template<int,int> class T1, template<int, int> class T2, template<int,int>class T3 >
T3<n,m> operator*(T1<n,k>&&, T2<k,m>&&)//does not work
当我尝试运行上面的代码(以明显的方式填充主体)时,我收到一个错误:
无法从Matrix <1,1>转换为Matrix <1,1> &&
当参数是左值时。
是。从我自己的代码:
template
<
int LeftColumnsRightRows, int LeftRows,
int RightColumns
>
Matrix<RightColumns, LeftRows> operator*(Matrix<LeftColumnsRightRows, LeftRows> const& a, Matrix<RightColumns, LeftColumnsRightRows> const& b)
我不知道为什么你要它采取&&
s。如果要将其他两种类型转换为矩阵然后将它们相乘,则应在乘法运算符之外进行转换。
我也会坚持使用const引用,正如之前的回答所解释的那样。但为了澄清为什么您的代码不起作用,完美转发仅适用于对cv-unqualified模板参数使用rvalue引用时。通俗地说,它必须只是T&&
,其中T
是一个函数模板参数:
template<class T>
void ForwardMe(T&& t)
{
DoSomething(std::forward<T>(t));
}
这个想法是编译器能够在传递左值时将T
推导为type&
(因此函数签名因参考折叠规则而变为void ForwardMe(type&)
),或者只是在rvalues(签名变为type
)的情况下void ForwardMe(type&&)
。
在您的示例中,您执行以下操作:
template<int N, template<int> class T>
void ForwardMe(T<N>&& t)
{
// ...
}
这不像你预期的那样工作,因为编译器不能推断T
是对某事物的引用,所以你不能有完美的转发。因此,函数参数t
仅匹配rvalue引用。
由于const引用可以绑定到临时对象,因此在上面的示例中使用const T<N>&
将解决您的问题。但是如果你真的想同时支持左值和右值输入(因为你喜欢在适当的地方使用移动语义),你有两个选择:
后者将是这样的:
#include <type_traits>
template<class L, class R>
struct MatrixMulResult_helper;
template<int n, int m, int k, template<int, int> class T>
struct MatrixMulResult_helper<T<n, m>, T<m, k>> { using type = T<n, k>; };
template<class L, class R>
using MatrixMulResult = typename MatrixMulResult_helper<L, R>::type;
template<class L, class R>
MatrixMulResult<std::decay_t<L>, std::decay_t<R>>
operator*(L&& lhs, R&& rhs)
{
// ...
}
编译器现在可以自由推导出L
和R
作为参考。 MatrixMulResult<>
确保此函数仅在(衰变类型)L
和R
分别为T<n,m>
和T<m,k>
形式时定义。它返回一个T<n,k>
。