C++ 模板运算符重载
C++ Template operator overload
我正在编写一个模板矩阵类,我对重载 * 运算符的工作方式有点困惑。
我想重载这样的东西(省略不相关的代码):
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*
,它通过常量引用获取vector3
和matrix4t
并产生另一个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>
返回类型中(其中A
和B
分别是被乘的矩阵类型和结果)。
从这里开始,您应该决定您需要或想要实现的内容,并且您可能希望提出更具体的问题。
- 为什么Mat类的两个对象可以在不重载运算符+的情况下添加
- 重载运算符new[]的行为取决于析构函数
- 为什么将值返回函数传递给重载=运算符对运算符函数有效,而对其他运算符无效
- 在 myVector 类中重载运算符 + 时出错
- 为什么常量词在重载运算符中不与 ostream 对象一起使用<<?
- 如何在 cpp 中重载运算符 +=?
- C++ 如何重载 [] 运算符并进行函数调用
- 重载运算符的范围是什么?它是否会影响作为类成员的集合的插入函数?
- 为什么我可以在不重载 "=" 运算符的情况下将一个对象分配给另一个对象?
- 重载运算符有地址吗?
- 如何迭代重载运算符 [] 的类?
- 重载运算符与添加问题
- 模板基类中的重载运算符
- 如何调用用于重载运算符"<<"的 friend 函数?
- 在 C++17 中的命名空间和子命名空间中重载运算符是不明确的
- 重载运算符<<采用谷歌 C++ 风格
- C++ 如何正确重载 + 运算符
- cout (<<) 重载运算符不打印减去的矩阵
- 如何在 c++ 中重载运算符 + 以便能够 whrite c_str = "smth" + c_str;
- 重载运算符*以获取对另一个类的实例的引用