C++ 3d矢量算术模板(如何专门处理整型和浮点型)
我想制作一个通用模板,指定3D向量上的所有3D数学,然后将其专门化为浮点(double)(称为Vec3d)和整数(称为Vec3i)。我希望在不重新实现公共代码的情况下完成此操作 有人建议通过继承而不是专门化来做这件事。但当我这样做时,我会出现以下错误:C++ 3d矢量算术模板(如何专门处理整型和浮点型),c++,templates,C++,Templates,我想制作一个通用模板,指定3D向量上的所有3D数学,然后将其专门化为浮点(double)(称为Vec3d)和整数(称为Vec3i)。我希望在不重新实现公共代码的情况下完成此操作 有人建议通过继承而不是专门化来做这件事。但当我这样做时,我会出现以下错误: main.cpp:34:12: error: could not convert ‘dR.Vec3d::<anonymous>.Vec3TYPE<TYPE>::operator*<double>(k)’ fr
main.cpp:34:12: error: could not convert ‘dR.Vec3d::<anonymous>.Vec3TYPE<TYPE>::operator*<double>(k)’ from ‘Vec3TYPE<double>’ to ‘Vec3d’
main.cpp:34:12:错误:无法将'dR.Vec3d::.Vec3TYPE::operator*(k)'从'Vec3TYPE'转换为'Vec3d'
返回dR*k;//这是一个错误
代码如下(摘自相关部分):
#包括
#包括
//通用模板的定义
模板
类Vec3TYPE{
公众:
联合{
结构{TYPE x,y,z;};
结构{TYPE a,b,c;};
类型数组[3];
};
内联空集(f型){x=f;y=f;z=f;};
内联无效集(类型fx,类型fy,类型fz){x=fx;y=fy;z=fz;};
内联void集(constvec3type&v){x=v.x;y=v.y;z=v.z;};
内联Vec3TYPE操作符+(TYPE f)常量{Vec3TYPE vo;vo.x=x+f;vo.y=y+f;vo.z=z+f;返回vo;};
内联Vec3TYPE运算符*(TYPE f)常量{Vec3TYPE vo;vo.x=x*f;vo.y=y*f;vo.z=z*f;返回vo;};
内联Vec3TYPE操作符+(const Vec3TYPE&vi)const{Vec3TYPE vo;vo.x=x+vi.x;vo.y=y+vi.y;vo.z=z+vi.z;返回vo;};
内联Vec3TYPE运算符-(const Vec3TYPE&vi)const{Vec3TYPE vo;vo.x=x-vi.x;vo.y=y-vi.y;vo.z=z-vi.z;返回vo;};
内联Vec3TYPE运算符*(const Vec3TYPE&vi)const{Vec3TYPE vo;vo.x=x*vi.x;vo.y=y*vi.y;vo.z=z*vi.z;返回vo;};
内联Vec3TYPE运算符/(const Vec3TYPE&vi)const{Vec3TYPE vo;vo.x=x/vi.x;vo.y=y/vi.y;vo.z=z/vi.z;返回vo;};
};
//专业化
类Vec3i:public Vec3TYPE{};//整型
类Vec3d:公共Vec3TYPE{//浮点版本
公众:
内联双范数()常量{返回sqrt(x*x+y*y+z*z);};
};
内联Vec3d getForce(Vec3d dR,双k){
返回dR*k;//有错误
}
//主要
int main(){
向量3D a;a.集(1.0,2.0,3.0);
//这很有效
vec3db;b.set(a*4.0);
printf(“%f%f%f\n”,b.x,b.y,b.z);
//这是不可能的
Vec3d b_;b_uu.set(getForce(a,4.0));
printf(“%f%f%f\n”,b.x,b.y,b.z);
}
问题在于Vec3TYPE::operator*
返回类型为Vec3TYPE
的对象<另一方面,code>getForce必须返回一个Vec3d
。设计的一个简单解决方法是,通过添加以下构造函数,使Vec3TYPE
可从Vec3TYPE
构造Vec3d
,该构造函数通过参数复制构造基本对象
Vec3d(const Vec3TYPE<double>& parent): Vec3TYPE<double>(parent){}
错误消息很可怕,但原因是没有从
Vec3TYPE
转换到Vec3d
(dR.Vec3d::.Vec3TYPE::operator*(k)
指的是操作的结果dR*k
,这并不是世界上最明显的事情。)
没有转换的原因是没有从基类到子类的默认转换
需要转换的原因是operator*
返回的是Vec3TYPE
,而不是Vec3d
如果您真的想使用继承,您需要在
Vec3d
中提供一个构造函数,该构造函数采用Vec3TYPE
。正如其他答案中所解释的,这个问题是由于使用继承而没有很好的理由造成的。这里不要使用继承。此外,对于一般功能,我将使用非成员函数,例如(在与Vec3TYPE
相同的命名空间中声明)
使用我在评论中提到的方法,你可以做一些类似的事情
template <typename TYPE, typename CHILD>
class Vec3TYPE{
public:
union{
struct{ TYPE x,y,z; };
struct{ TYPE a,b,c; };
TYPE array[3];
};
inline CHILD operator+ ( TYPE f ) const { CHILD vo; vo.x=x+f; vo.y=y+f; vo.z=z+f; return vo; };
// etc.
};
// specialization
class Vec3i : public Vec3TYPE<int, Vec3i>{}; // int version
class Vec3d : public Vec3TYPE<double, Vec3d>{ // float version
public:
inline double norm ( ) const { return sqrt( x*x + y*y + z*z ); };
};
模板
类Vec3TYPE{
公众:
联合{
结构{TYPE x,y,z;};
结构{TYPE a,b,c;};
类型数组[3];
};
内联子运算符+(类型f)常量{CHILD vo;vo.x=x+f;vo.y=y+f;vo.z=z+f;返回vo;};
//等等。
};
//专业化
类Vec3i:public Vec3TYPE{};//整型
类Vec3d:公共Vec3TYPE{//浮点版本
公众:
内联双范数()常量{返回sqrt(x*x+y*y+z*z);};
};
似乎有一些额外的大括号和一些缺少的分号、不一致的缩进以及一些额外的不必要的分号。请复制粘贴实际代码,而不是在文本框中重写。或者更好,请创建一个并向我们展示;在Vec3Type{}类的末尾;,而且方法不需要;。但是,假设你对数学向量而不是语法感兴趣,看看这里继承的意义是什么?Vec3d
如何扩展其基础Vec3TYPE
?在您的代码片段中,继承没有解决任何问题,因此毫无意义。是的,它导致了你的问题。好的,对不起。我现在制作了推荐的“最小工作示例”。您可能想了解。您好,是的,我理解为什么会出现此错误。我只是不知道如何克服它。如果可以通过继承以外的方式进行这种类型专门化,我会这样做。我只是不想为每个特定类型重写向量数学的实现。好的,我只想在不多次重新实现所有功能的情况下创建Vec3d和Vec3i类型。2) 因为结果不是整数。(好的,这只是一个例子,最初我在这里有normalize())1)这个复制构造需要一些性能(?)2)如果我指定构造函数,我可能无法通过getForce({1.0,2.0,3.0},10)1)这样的列表初始化变量。编译器可能会通过将操作符*
的结果直接写入Vec3d
的子对象来删除副本,但您必须进行测试才能确定。这个建议主要是一个快速的创可贴不会改变设计。更好的设计是使用CRTP,比如Joa
template<class Rtype = TYPE> // the default param requires c++11
inline RType norm ( ) const { return sqrt( x*x + y*y + z*z ); };
inline double norm(Vec3TYPE<double> const&v) noexcept
{
return v[0]*v[0] + v[1]*v[1] + v[2]*v[2];
}
typedef Vec3TYPE<double> Vec3d;
typedef Vec3TYPE<int> Vec3i;
template <typename TYPE, typename CHILD>
class Vec3TYPE{
public:
union{
struct{ TYPE x,y,z; };
struct{ TYPE a,b,c; };
TYPE array[3];
};
inline CHILD operator+ ( TYPE f ) const { CHILD vo; vo.x=x+f; vo.y=y+f; vo.z=z+f; return vo; };
// etc.
};
// specialization
class Vec3i : public Vec3TYPE<int, Vec3i>{}; // int version
class Vec3d : public Vec3TYPE<double, Vec3d>{ // float version
public:
inline double norm ( ) const { return sqrt( x*x + y*y + z*z ); };
};