假设我有一个模板类,例如
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&lt; 1,1&gt;到Matrix&lt; 1,1&gt;&amp;&amp;
当参数是左值时。
答案 0 :(得分:2)
是。从我自己的代码:
template
<
int LeftColumnsRightRows, int LeftRows,
int RightColumns
>
Matrix<RightColumns, LeftRows> operator*(Matrix<LeftColumnsRightRows, LeftRows> const& a, Matrix<RightColumns, LeftColumnsRightRows> const& b)
而且我不知道你为什么要这样做&&
。如果要将其他两种类型转换为矩阵然后乘以它们,则应在乘法运算符之外进行转换。
答案 1 :(得分:2)
我也会坚持使用const引用,正如之前的回答所解释的那样。但为了澄清您的代码无法正常工作的原因,只有当您使用对cv-nonqualified模板参数的rvalue引用时,才能应用完美转发。在外行人的术语中,它必须只是T&&
,其中T
是函数模板参数:
template<class T>
void ForwardMe(T&& t)
{
DoSomething(std::forward<T>(t));
}
这个想法是,当传递左值时,编译器将能够将T
推导为type&
(因为参考折叠规则,函数签名变为void ForwardMe(type&)
),或者只是{ {1}}如果是rvalues(签名变为type
)。
在您的示例中,您执行以下操作:
void ForwardMe(type&&)
这并不像您预期的那样有效,因为编译器无法推断template<int N, template<int> class T>
void ForwardMe(T<N>&& t)
{
// ...
}
是对某事物的引用,因此您无法完成转发。因此,函数参数T
仅匹配右值引用。
由于const引用可以绑定到临时对象,因此在上面的示例中使用t
将解决您的问题。但是如果你真的想同时支持左值和右值输入(因为你喜欢在适当的地方使用移动语义),你有两个选择:
后者将是这样的:
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>
。