gpt4 book ai didi

C++ 模板运算符重载

转载 作者:太空狗 更新时间:2023-10-29 21:04:12 25 4
gpt4 key购买 nike

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

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

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

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

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

干杯

最佳答案

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

friend vector3 operator*(const vector3 &v, const matrix4t &m);
template <typename scalarT>
friend scalarT operator*(const scalarT &inputSclT, const matrix4t &inputM4t);

这些是 friend 声明。友元声明声明(告诉编译器存在)类外部的实体,并且应授予此类实体对此类内部(在本例中为模板)的完全访问权限。第二个 friend 声明是一个自由函数模板 operator*,它通过 const 引用获取 scalarT 类型和 matrix4T<T> 对象,并产生一个 scalarT 值。这个 friend 声明看起来很奇怪,因为矩阵乘以一个标量值通常会产生另一个相同维度的矩阵,而不仅仅是一个标量值。

请注意,在类模板中,模板 matrix4t 的名称不是指模板,而是指特定的特化(即它代表 matrix4t<T> ,而不是模板的名称)。这种区别现在看起来可能并不重要,但迟早你会意识到它的重要性。

第二个声明是一个非模板化的自由函数 operator* ,它通过常量引用获取 vector3matrix4t 并产生另一个 vector3 。由于我们在 matrix4t 的定义中,模板的名称指的是专门化 matrix4t<T> ,但 vector3 仅指模板,而不是任何特定的实例化。您应该将其设为接受任何给定类型 vector3<U>U 的模板,或者将其设为接受单一类型(可以是我们模板的 T 参数)的非模板化函数: vector3<T> 。与其他声明一样,返回值可能关闭或不关闭……取决于 vector 的维度(是行还是列?)

关于实际的交友,我建议您阅读 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*=

    对于乘以 vector 的情况(并且因为它不是对称的),分派(dispatch)到单个实现的技巧将不起作用,但是您可以将这两个实现作为非模板化的 friend 提供,如上所述。

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

    从这里开始,您应该决定您需要或想要实现什么,并且您可能想在出现时提出更具体的问题。

    关于C++ 模板运算符重载,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/11854371/

    25 4 0
    Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
    广告合作:1813099741@qq.com 6ren.com