如何为模板化类声明类外二进制运算符
How does one declare an out of class binary operator for a templated class?
我有一种情况,我有一些数学运算,为了方便起见,可以重载。
但其中一些在其他类型上运行。
像
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));
}
};
我读过,最好只在"类外"实现*、+、-、/等的运算符,或者让编译器从类中的+=版本中推导出一些内容。
- 与在类中实现+相比,这是最优的吗
- 如果左手边的参数是另一种类型,那么如何对相反的情况进行处理
Ie在我的特殊情况下,模板化运算符有两个模板类型参数。一个是元素的类型,另一个是模板实现其方法的超类。
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));
}
我确实读了运营商过载问题的大部分答案。
我确实回答了很多问题。但是不包括模板的ramafacations和在这些模板的子类中使用的声明运算符的模板。
对于所有必须选择将其作为成员函数或非成员函数实现的运算符,请使用以下经验法则来决定:
这在一定程度上有助于我了解实现的最佳方式,无论是在课堂外还是在课堂内。
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也会出现类似的问题。
我确实发现我真的必须在同一级别解密所有可能冲突的运算符,以便过载解决方案如预期那样工作。ie:所有这些都在子类的同一个超类中,如果在该超类的超类中声明了poerator,它们有时会被忽略——如果有一些任性的转换为优先级较高的重载之一(arrrgh)提供了一个参数。
在这一点上,我似乎已经解决了所有的编译问题——现在把它链接起来哈哈哈!!
假设你的类型移动起来很便宜:
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类型,在内部使用廉价的移动存储类型。
这种技术创造了我所说的柯尼希算子;非模板运算符onky可通过ADL从模板类中发现。与成员函数运算符和非成员模板运算符相比,这有许多优点。在这种简单的情况下,情况就不那么简单了,但作为一个盲目的接受者,它避免了一堆陷阱(比如,使用运算符std::string不会让你成为<<
流)。
- 将成员变量添加到共享库中的类中,不会破坏二进制兼容性吗
- .cpp和.h文件中的模板专用化声明
- 未在作用域中声明unordered_map
- C++避免重复声明的语法是什么
- 有根的二进制搜索树.保留与其父级的链接
- 如何确保C++函数在定义之前声明(如override关键字)
- 错误:未在此范围内声明'reverse'
- 多态二进制函数
- 奇怪的(对我来说)返回声明 - 在谷歌上找不到任何关于它的信息
- 为什么在定义函数之前先声明它
- 如何声明特征矩阵,然后通过嵌套循环初始化它
- #ifdef和未声明的标识符
- 没有显式声明的int[]中的foreach
- 为什么我不能定义一元运算符,然后在 MSVC 的模板类中声明具有相同名称的友元二进制运算符?
- 二进制加法过载声明语法错误
- 没有变量声明为函数,但错误:二进制表达式的操作数无效
- 如何为模板化类声明类外二进制运算符
- 从GCC 2.95生成的ELF二进制文件中恢复c++类声明
- 当数字声明为uint32和uint64时,将整数转换为二进制会显示不同的输出
- 在c++中如何声明二进制信号量