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