在某些情况下,为了方便起见,我有一些数学运算可以重载。
但是其中一些可以在其他类型上运行。
像
vec3<type> * type
和
type * vec3<type>
用于标量的右手参数的一种方法是:
template<class T, class SubT>
class Vec3 {
// this is fine, ie: works
SubT operator *(const T &val) {
return(SubT(x*val,y*val,z*val));
}
};
我读到最好仅在*,+,-,/等“类外”实现运算符,或者让编译器从类中的+ =版本推论出东西。
在我的特殊情况下,模板化运算符具有两个模板类型参数。一个是元素的类型,另一个是模板正在为其实现方法的超类。
template<class T, class SubT>
SubT operator *(const T &a, const Vec3Base<T, B> &b) {
return(b * a);
}
无论如何,希望你能得到我的愿望,如何正确地做到这一点是一个问题:)
就像我只需要采取一种类型?即:向量类型,然后从中获取元素类型为typedef ??
template<class VT>
VT::SubT operator*(const VT::ElemT &a, const VT &v) {
return(v * a);
}
并且我还应该使用另一种方式而不是在类中,而是通过以下方式实现:
template<class VT>
VT::SubT operator*(const VT &a, const VT::ElemT &b ) {
return(VT::SubT(a.x*b,a.y*b,a.z*b));
}
我确实阅读了惯用运算符重载问题的大部分答案。
我确实回答了很多事情。但是,BUT并未涵盖模板和模板的详细说明,它们声明了在这些模板的子类中使用的运算符。
对于必须选择将其实现为成员函数或非成员函数的所有运算符,请使用以下经验法则来决定:
这对我希望了解在课堂外还是课堂上实现最佳实施方式的希望有所帮助。
If it is a unary operator, implement it as a member function. If a binary operator treats both operands equally (it leaves them unchanged), implement this operator as a non-member function. If a binary operator does not treat both of its operands equally (usually it will change its left operand), it might be useful to make
它是其左操作数类型的成员函数(如果必须访问) 操作数的私有部分。
我想知道模板是否存在优先顺序问题。我发现是否在模板中声明了运算符,并且它是子类的超类,至少在MS编译器中它继承了它的运算符,因此它将优先于全局类中的全局类。讨厌 !!! clang和gcc也会发生类似的问题。
我确实发现我确实必须在相同级别上消除所有可能发生冲突的运算符,以便重载解析按预期进行。即:所有子类都在同一个超类中,如果在超类的超类中声明了Poerator,则有时会忽略它们,似乎有某种任性的转换会以更高的优先级为其中一个重载提供参数( arrrgh)。
目前看来我已经解决了所有编译问题-现在将其链接到哈哈哈!!
答案 0 :(得分:0)
假设您的类型价格便宜:
template<class T, class SubT>
class Vec3 {
// this is fine, ie: works
SubT& operator *=(const T &val) & {
x*=val;y*=val;z*=val;
return *this;
}
friend SubT operator*(Vec3 v, T const& t){
v*=t;
return v;
}
friend SubT operator*(T const& t, Vec3 v){
v*=t;
return v;
}
};
一个3元组的数字移动几乎总是便宜的,因为这些数字很小(如64位)并且可以复制,或者它们将成为bignum类型,在内部使用便宜的存储类型进行移动。< / p>
这种技术创造了我所谓的Koenig运算符;非模板运算符可以通过ADL从模板类中发现。与成员函数运算符和非成员模板运算符相比,它具有许多优点。在这种简单的情况下,情况有所减少,但是作为一种盲目的方法,它避免了很多陷阱(例如,如何让运算符std :: string不能让您<<
流式传输)。