Warning: file_get_contents(/data/phpspider/zhask/data//catemap/3/templates/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C++ 3d矢量算术模板(如何专门处理整型和浮点型)_C++_Templates - Fatal编程技术网

C++ 3d矢量算术模板(如何专门处理整型和浮点型)

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

我想制作一个通用模板,指定3D向量上的所有3D数学,然后将其专门化为浮点(double)(称为Vec3d)和整数(称为Vec3i)。我希望在不重新实现公共代码的情况下完成此操作

有人建议通过继承而不是专门化来做这件事。但当我这样做时,我会出现以下错误:

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