C++ 模板运算符重载

C++ Template operator overload

本文关键字:重载 运算符 C++      更新时间:2023-10-16

我正在编写一个模板矩阵类,我对重载 * 运算符的工作方式有点困惑。

我想重载这样的东西(省略不相关的代码):

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。此外,它还应该允许将我的矩阵与标量模板值相乘,该值可以是浮点数、双精度数等。这些方法的定义需要不同,以允许向量与标量乘法,因此不仅将模板用于两者

但是,在将此运算符与 vector3 一起使用时,编译器是否知道使用显式声明的 vector3 方法,或者它会尝试创建该方法的模板化版本,这将不起作用,因为定义被编写为仅允许标量值,并且可能还会抱怨方法重新定义。

关于这是否有效,或者我还能怎么做的任何想法?

干杯

我觉得您可能的目标是一个比需要的更复杂的解决方案,所以我将从头开始构建,并将一些细节留给以后。首先,我将开始分析您提出的语法及其含义。

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*,它通过常量引用获取vector3matrix4t并产生另一个vector3。由于我们在matrix4t的定义之内,模板的名称指的是专用化matrix4t<T>,但vector3只指模板,而不是任何特定的实例化。你应该把它做成一个接受任何给定类型vector3<U>的模板U,或者做一个接受单一类型的非模板化函数(这可以是我们模板的T参数):vector3<T> .与其他声明相同,返回值可能关闭或不关闭...取决于向量的维度是多少(是行还是列?

关于实际的交友,我建议您阅读此答案以解决不同的类似问题。

对于实际运算符,对于标量类型,我建议采用以下方法:

  • 实现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*为自由函数(friendship仅用于为每个实例化类型提供免费函数,阅读链接答案)。

对于乘以

向量的情况(并且因为它不是对称的),调度到单个实现的技巧将不起作用,但您可以如上所述将两个实现作为非模板化友元提供。

如果要提供混合类型的操作,则上述所有内容都必须是模板。增加的复杂性不是模板,而是确定如果要升级类型,结果类型应该是什么。对于 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>返回类型中(其中AB分别是被乘的矩阵类型和结果)。

从这里开始,您应该决定您需要或想要实现的内容,并且您可能希望提出更具体的问题。