简体   繁体   English

C ++模板运算符重载

[英]C++ Template operator overload

I'm writing a template matrix class, and I am a bit confused as to how overloading the * operator would work. 我正在编写一个模板矩阵类,我对如何重载*运算符有点困惑。

I would want to overload something like this (omitting irrelevant code): 我想要重载这样的东西(省略不相关的代码):

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&);

}

Assuming correct definitions for the individual multiplications I assume this should allow multiplication of my matrix object with an object of type vector3 from both sides of the operand, returning a vector3 each time. 假设单个乘法的正确定义,我假设这应该允许我的矩阵对象与操作数两侧的vector3类型的对象相乘,每次返回一个vector3。 Also it should allow multiplication of my matrix with a scalar template value, which could be float, double etc. The definitions of these methods would need to be different, to allow for vector vs scalar multiplication, hence not just using the template for both 此外,它应该允许我的矩阵与标量模板值相乘,这可能是浮点数,双精度等。这些方法的定义需要不同,以允许矢量与标量乘法,因此不仅仅使用模板

On using this operator with a vector3 though, would the compiler know to use the explicitly declared vector3 method, or would it try and create the templated version of the method, which would not work as the definition is written to only allow for a scalar value, and probably also then complain about method redefinition. 虽然将此运算符与vector3一起使用,编译器是否会知道使用显式声明的vector3方法,或者它是否会尝试创建方法的模板化版本,这不会起作用,因为定义只是为了允许标量值,然后可能还抱怨方法重新定义。

Any thoughts on if this would work, or how else I could go about it? 关于这是否有用的任何想法,或者我怎么能去做呢?

Cheers 干杯

I have the feeling that you might be aiming for a more complex solution than needed, so I will start building from the ground up, and leave some details for later. 我觉得你可能会想要一个比需要更复杂的解决方案,所以我将从头开始构建,并留待一些细节供以后使用。 First I will start analyzing your proposed syntax and what it means. 首先,我将开始分析您提出的语法及其含义。

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

These are friend declarations. 这些是朋友声明。 Friend declarations declare (tell the compiler that there is) an entity external to the class and that such an entity should be granted full access to the internals of this class (which in this case is a template). 朋友声明声明 (告诉编译器有)该类外部的实体,并且应该授予这样一个实体对该类的内部(在本例中是模板)的完全访问权。 The second friend declaration is of a free function template operator* that takes a scalarT type and a matrix4T<T> object both by const reference and yields an scalarT value. 第二个朋友声明是一个自由函数模板operator* ,它通过const引用获取scalarT类型和matrix4T<T>对象,并产生标量scalarT值。 This friend declaration seems strange in that the multiplication of a matrix by a scalar value usually yields another matrix of the same dimensions, rather than just a scalar value. 这个朋友声明似乎很奇怪,因为矩阵乘以标量值通常会产生另一个相同维度的矩阵,而不仅仅是标量值。

Note that inside the class template, the name of the template matrix4t does not refer to the template, but the particular specialization (ie it represents matrix4t<T> , not the name of the template). 请注意,在类模板中,模板matrix4t的名称不是指模板,而是指特定的特化(即它表示matrix4t<T> ,而不是模板的名称)。 The distinction might not seem important now, but sooner or later you will realize the importance of it. 这种区别现在似乎并不重要,但迟早你会意识到它的重要性。

The second declaration is of a non-templated free function operator* that takes a vector3 and a matrix4t both by const reference and yields another vector3 . 第二个声明是一个非模板化的自由函数operator* ,它通过const引用获取vector3matrix4t ,并产生另一个vector3 Since we are inside the definition of the matrix4t , the name of the template refers to the specialization matrix4t<T> , but vector3 refers just to the template , and not any particular instantiation. 由于我们在matrix4t的定义中,模板的名称引用了特化matrix4t<T> ,但是vector3仅指模板 ,而不是任何特定的实例化。 You should either make that a template that accepts vector3<U> for any given type U , or else a non-templated function that accepts a single type (which can be the T argument of our template): vector3<T> . 您应该为任何给定类型U创建一个接受vector3<U>的模板,或者接受单个类型(可以是我们模板的T参数)的非模板化函数: vector3<T> In the same way as with the other declaration, the return value might be off or not... depends on what are the dimensions of the vector (is it row or column?) 以与其他声明相同的方式,返回值可能关闭或不关闭...取决于向量的维度(是行还是列?)

Regarding the actual befriending, I recommend that you read this answer to a different similar question. 关于实际的朋友,我建议你阅读这个答案来解决另一个类似的问题。

As of the actual operators, for the scalar type, I would suggest the following approach: 截至实际运算符,对于标量类型,我建议采用以下方法:

  • Implement operator*= taking the scalar of the same type as is stored as an argument 实现operator*=获取与存储为参数的标量相同的标量
  • Implement both versions of operator* in terms of 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;
    }
};

Notes: operator*= is implemented once, taking the matrix as left hand side (you could also offer an overload taking the matrix as right hand side, but it would look a bit strange: 5 *= matrix yielding a matrix...). 注意: operator*=实现一次,将矩阵作为左侧(你也可以提供一个过载,将矩阵作为右侧,但它看起来有点奇怪: 5 *= matrix产生一个矩阵......) 。 Implement operator* as free functions (friendship is only used to provide the free function for each instantiating type, read the linked answer), by forwarding to operator*= . operator*实现为自由函数(友谊仅用于为每个实例化类型提供自由函数,读取链接的答案),通过转发给operator*=

For the case of multiplying by a vector (and because it is not symmetric) the trick of dispatching to a single implementation will not work, but you can provide the two implementations as non-templated friends as above. 对于乘以向量(并且因为它不对称)的情况,调度到单个实现的技巧将不起作用,但是您可以将这两个实现提供为如上所述的非模板化朋友。

If you wanted to provide operations with mixed types, then all of the above would have to be templates. 如果您想提供混合类型的操作,那么上述所有操作都必须是模板。 The added complexity is not the template, but rather determining what the result types should be if you want to promote the types. 增加的复杂性不是模板,而是确定如果要提升类型,结果类型应该是什么。 With C++11 the easiest way would be using decltype and trailing return types: 使用C ++ 11最简单的方法是使用decltype和尾随返回类型:

template <typename U>
friend auto operator*( matrixt4 lhs, U scalar ) -> matrix4t< decltype(scalar * element(0,0) ) > {
   // implement here
}

And similarly for operator*(scalar,matrix) . 对于operator*(scalar,matrix)也是类似的。 Note that if you are promoting types, operator*= might not make sense at all (as the type would be the same as the lhs), or if it did, it might or might not produce the result that you want. 请注意,如果要提升类型, operator*=可能根本没有意义(因为类型与lhs相同),或者如果它有,它可能会或可能不会产生您想要的结果。 If you consider doing it, the operator+ would have to take the matrix4t<A> argument by reference (as it might not be of the appropriate type) and copy into the matrix4t<B> return type (where A and B are respectively the types of the matrix being multiplied and the result). 如果你考虑这样做, operator+必须通过引用获取matrix4t<A>参数(因为它可能不是合适的类型)并复制到matrix4t<B>返回类型(其中AB分别是类型)矩阵的乘法和结果)。

From here on, you should decide what you need or want to implement, and you might want to ask more specific questions as they come by. 从现在开始,您应该决定您需要或想要实施的内容,并且您可能希望在提出时提出更具体的问题。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM