Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/cplusplus/134.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

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++ 我可以将模板强制转换/转换为其他模板类型吗?_C++_Templates - Fatal编程技术网

C++ 我可以将模板强制转换/转换为其他模板类型吗?

C++ 我可以将模板强制转换/转换为其他模板类型吗?,c++,templates,C++,Templates,我正在编写一些代码,需要经常在同质坐标和笛卡尔坐标之间切换: (x, y, z) -> (x, y, z, w = 1) (x, y, z, w) -> (x/w, y/w, z/w) 我正在使用一个库,它已经为任意大小和类型的向量提供了模板,并且为一些常见的向量提供了typedef,如: typedef vec<3, float> Vec3f; typedef vec<4, float> Vec4f; 下面是标题中的相关模板代码,请注意,我添加了ve

我正在编写一些代码,需要经常在同质坐标和笛卡尔坐标之间切换:

(x, y, z) -> (x, y, z, w = 1)
(x, y, z, w) -> (x/w, y/w, z/w)
我正在使用一个库,它已经为任意大小和类型的向量提供了模板,并且为一些常见的向量提供了typedef,如:

typedef vec<3,  float> Vec3f;
typedef vec<4,  float> Vec4f;
下面是标题中的相关模板代码,请注意,我添加了vec部分:

#包括
#包括
#包括
#包括
模板类垫;
模板结构向量{
vec(){for(size_t i=DIM;i--;data_[i]=t());}
T&运算符[](const size_T i){assert(i您可以子类化

class Homogeneous;
class Cartesian : public Vec3f
{
    Cartesian () : Vec3f() {}
    Cartesian (float a, float b, float c) : Vec3f(a, b, c, d) {}
    explicit Cartesian (const Homogeneous& v); // Define later, we don't know Homogeneous yet
}

class Homogeneous : public Vec4f
{
public:
    Homogeneous() : Vec4f() {}
    Homogeneous(float a, float b, float c, float d) : Vec4f(a, b, c, d) {}
    explicit Homogeneous(const Cartesian& v) : Vec4f() { // do conversion }
}

Cartesian::Cartesian (const Homogeneous& v) : Vec3f() { // do conversion }
类似的东西。它还有一个额外的好处,就是比使用Vec3f更安全

如果您在没有虚拟析构函数的情况下使用public inheritance,您应该执行以下操作

static_assert(sizeof(Cartesian) == sizeof(Vec3f), "Don't");
static_assert(sizeof(Homogeneous) == sizeof(Vec4f), "Don't");

注意。

你能解释一下最后一部分吗?我应该把这些静态断言放在哪里?当你进行公共继承时,你应该a)使用多态性(有一个虚拟析构函数)或者b)确保大小保持不变(你不能向类中添加任何占用大小的成员);您可以通过将
static_assert
放在代码中的任何位置(但最好的位置应该在类定义的正下方)来确保。因此,当您为
笛卡尔
对象调用
~Vec3f
时,您知道没有泄漏。
#include <cmath>
#include <vector>
#include <cassert>
#include <iostream>

template<size_t DimCols,size_t DimRows,typename T> class mat;

template <size_t DIM, typename T> struct vec {
    vec() { for (size_t i=DIM; i--; data_[i] = T()); }
          T& operator[](const size_t i)       { assert(i<DIM); return data_[i]; }
    const T& operator[](const size_t i) const { assert(i<DIM); return data_[i]; }
private:
    T data_[DIM];
};

/////////////////////////////////////////////////////////////////////////////////

template <typename T> struct vec<3,T> {
    vec() : x(T()), y(T()), z(T()) {}
    vec(T X, T Y, T Z) : x(X), y(Y), z(Z) {}
    template <class U> vec<3,T>(const vec<3,U> &v);
          T& operator[](const size_t i)       { assert(i<3); return i<=0 ? x : (1==i ? y : z); }
    const T& operator[](const size_t i) const { assert(i<3); return i<=0 ? x : (1==i ? y : z); }
    float norm() { return std::sqrt(x*x+y*y+z*z); }
    vec<3,T> & normalize(T l=1) { *this = (*this)*(l/norm()); return *this; }

    T x,y,z;
};

/////////////////////////////////////////////////////////////////////////////////

// my Vec4f template
template <typename T> struct vec<4,T> {
    vec() : x(T()), y(T()), z(T()), w(T()) {}
    vec(T X, T Y, T Z) : x(X), y(Y), z(Z), w(1.f) {}
    template <class U> vec<4,T>(const vec<4,U> &v);
          T& operator[](const size_t i)       { assert(i<4); return i<=0 ? x : (1==i ? y : (2==i ? z : w)); }
    const T& operator[](const size_t i) const { assert(i<4); return i<=0 ? x : (1==i ? y : (2==i ? z : w)); }

    T x,y,z,w;
};

typedef vec<3,  float> Vec3f;
typedef vec<4,  float> Vec4f;
template <> template <> vec<3,int>  ::vec(const vec<3,float> &v) : x(int(v.x+.5f)),y(int(v.y+.5f)),z(int(v.z+.5f)) {};
template <> template <> vec<3,float>::vec(const vec<3,int> &v)   : x(v.x),y(v.y),z(v.z) {};
template <> template <> vec<3,float>::vec(const vec<4,float> &v) : x(v.x / v.w),y(v.y / v.w),z(v.z / v.w) {};
template <> template <> vec<4,float>::vec(const vec<3,float> &v) : x(v.x),y(v.y),z(v.z),w(1.f) {};
tinyrenderer-files/geometry.cpp:9:25: error: template-id ‘vec<>’ for ‘vec<3, float>::vec(const vec<4, float>&)’ does not match any template declaration
 template <> template <> vec<3,float>::vec(const vec<4,float> &v) : x(v.x / v.w),y(v.y / v.w),z(v.z / v.w) {};
                         ^~~~~~~~~~~~
In file included from tinyrenderer-files/geometry.cpp:1:0:
tinyrenderer-files/geometry.h:32:30: note: candidates are: constexpr vec<3, float>::vec(vec<3, float>&&)
 template <typename T> struct vec<3,T> {
                              ^~~~~~~~
tinyrenderer-files/geometry.h:32:30: note:                 constexpr vec<3, float>::vec(const vec<3, float>&)
tinyrenderer-files/geometry.h:35:24: note:                 template<class U> vec<3, T>::vec(const vec<3, U>&) [with U = U; T = float]
     template <class U> vec<3,T>(const vec<3,U> &v);
                        ^~~~~~~~
tinyrenderer-files/geometry.h:34:5: note:                 vec<3, T>::vec(T, T, T) [with T = float]
     vec(T X, T Y, T Z) : x(X), y(Y), z(Z) {}
     ^~~
tinyrenderer-files/geometry.h:33:5: note:                 vec<3, T>::vec() [with T = float]
     vec() : x(T()), y(T()), z(T()) {}
     ^~~
tinyrenderer-files/geometry.cpp:10:25: error: template-id ‘vec<>’ for ‘vec<4, float>::vec(const vec<3, float>&)’ does not match any template declaration
 template <> template <> vec<4,float>::vec(const vec<3,float> &v) : x(v.x),y(v.y),z(v.z),w(1.f) {};
                         ^~~~~~~~~~~~
In file included from tinyrenderer-files/geometry.cpp:1:0:
tinyrenderer-files/geometry.h:47:30: note: candidates are: constexpr vec<4, float>::vec(vec<4, float>&&)
 template <typename T> struct vec<4,T> {
                              ^~~~~~~~
tinyrenderer-files/geometry.h:47:30: note:                 constexpr vec<4, float>::vec(const vec<4, float>&)
tinyrenderer-files/geometry.h:50:24: note:                 template<class U> vec<4, T>::vec(const vec<4, U>&) [with U = U; T = float]
     template <class U> vec<4,T>(const vec<4,U> &v);
                        ^~~~~~~~
tinyrenderer-files/geometry.h:49:5: note:                 vec<4, T>::vec(T, T, T) [with T = float]
     vec(T X, T Y, T Z) : x(X), y(Y), z(Z), w(1.f) {}
     ^~~
tinyrenderer-files/geometry.h:48:5: note:                 vec<4, T>::vec() [with T = float]
     vec() : x(T()), y(T()), z(T()), w(T()) {}
     ^~~
class Homogeneous;
class Cartesian : public Vec3f
{
    Cartesian () : Vec3f() {}
    Cartesian (float a, float b, float c) : Vec3f(a, b, c, d) {}
    explicit Cartesian (const Homogeneous& v); // Define later, we don't know Homogeneous yet
}

class Homogeneous : public Vec4f
{
public:
    Homogeneous() : Vec4f() {}
    Homogeneous(float a, float b, float c, float d) : Vec4f(a, b, c, d) {}
    explicit Homogeneous(const Cartesian& v) : Vec4f() { // do conversion }
}

Cartesian::Cartesian (const Homogeneous& v) : Vec3f() { // do conversion }
static_assert(sizeof(Cartesian) == sizeof(Vec3f), "Don't");
static_assert(sizeof(Homogeneous) == sizeof(Vec4f), "Don't");