我正在写一个模板矩阵类,我对如何重载*运算符有点困惑。
我想要重载这样的东西(省略不相关的代码):
template<typename T>class Matrix4t
{
friend vector3 operator*(const vector3 &inputV3, const matrix4t &inputM4t);
template <typename scalarT>
friend scalarT operator*(const scalarT &inputSclT, const matrix4t &inputM4t);
public:
const matrix4t operator*(const matrix4t)
vector3 operator*(const vector3 &inputV3);
template <typename scalarT>
const matrix4t operator*(const scalarT&);
}
假设单个乘法的正确定义我假设这应该允许我的矩阵对象与操作数两侧的vector3类型的对象相乘,每次返回一个vector3。此外,它应该允许我的矩阵与标量模板值相乘,这可能是浮点数,双精度等。这些方法的定义需要不同,以允许矢量与标量乘法,因此不仅仅使用模板两者< / p>
虽然将此运算符与vector3一起使用,编译器是否会知道使用显式声明的vector3方法,或者它是否会尝试创建该方法的模板化版本,这将无法正常工作,因为定义只是为了允许标量值,然后可能还会抱怨方法重新定义。
有关这是否有用的想法,或者我还能怎么做呢?
干杯
答案 0 :(得分:4)
我觉得你可能会想要一个比需要更复杂的解决方案,所以我将从头开始构建,并留待一些细节供以后使用。首先,我将开始分析您提出的语法及其含义。
friend vector3 operator*(const vector3 &v, const matrix4t &m);
template <typename scalarT>
friend scalarT operator*(const scalarT &inputSclT, const matrix4t &inputM4t);
这些是朋友声明。朋友声明声明(告诉编译器有)该类外部的实体,并且应该授予此类实体对该类的内部(在本例中为模板)的完全访问权限。第二个朋友声明是一个自由函数模板operator*
,它通过const引用获取scalarT
类型和matrix4T<T>
对象,并产生scalarT
值。这个朋友声明看起来很奇怪,因为矩阵乘以标量值通常会产生另一个相同维度的矩阵,而不仅仅是一个标量值。
请注意,在类模板中,模板matrix4t
的名称不是指模板,而是指特定的特殊化(即它代表matrix4t<T>
,而不是模板的名称)。这种区别现在似乎并不重要,但迟早你会意识到它的重要性。
第二个声明是一个非模板化的自由函数operator*
,它通过const引用获取vector3
和matrix4t
并产生另一个vector3
。由于我们位于matrix4t
的定义范围内,因此模板的名称引用了专门化matrix4t<T>
,但vector3
仅指模板,而不是任何特定的实例。您应该为任何给定类型vector3<U>
创建一个接受U
的模板,或者接受一个类型的非模板化函数(可以是我们模板的T
参数):vector3<T>
。以与其他声明相同的方式,返回值可能关闭或不关闭...取决于向量的维度(是行还是列?)
关于实际的朋友,我建议您阅读this answer以查找其他类似的问题。
从实际运算符开始,对于标量类型,我建议采用以下方法:
operator*=
operator*
operator*=
的两个版本
template <typename T> class matrix4t {
public:
matrix4t& operator*=( T scalar ); // and implement
friend matrix4t operator*( matrix4t lhs, T scalar ) {
return lhs*=scalar;
}
friend matrix4t operator*( T scalar, matrix4t rhs ) {
return rhs*=scalar;
}
};
注意:operator*=
实现一次,将矩阵作为左手边(你也可以提供一个过载,将矩阵作为右手边,但看起来有点奇怪:5 *= matrix
屈服矩阵......)。将operator*
实现为自由函数(友谊仅用于为每个实例化类型提供自由函数,读取链接的答案),转发到operator*=
。
对于乘以向量(并且因为它不对称)的情况,调度到单个实现的技巧将不起作用,但是您可以将这两个实现提供为非模板化的朋友,如上所述。
如果您想提供混合类型的操作,那么以上所有内容都必须是模板。增加的复杂性不是模板,而是确定如果要提升类型,结果类型应该是什么。使用C ++ 11,最简单的方法是使用decltype
和尾随返回类型:
template <typename U>
friend auto operator*( matrixt4 lhs, U scalar ) -> matrix4t< decltype(scalar * element(0,0) ) > {
// implement here
}
同样适用于operator*(scalar,matrix)
。请注意,如果您要提升类型,operator*=
可能根本没有意义(因为类型与lhs相同),或者如果它有,它可能会或可能不会产生您想要的结果。如果您考虑这样做,operator+
必须通过引用获取matrix4t<A>
参数(因为它可能不是合适的类型)并复制到matrix4t<B>
返回类型(其中{ {1}}和A
分别是乘法矩阵的类型和结果。
从现在开始,您应该决定您需要或想要实施的内容,并且您可能希望在提出时提出更具体的问题。