如何重新定义POD类型,使其在保持语义的同时被视为不同的类型

  • 本文关键字:类型 语义 POD 定义 何重新 c++ types
  • 更新时间 :
  • 英文 :


想象一下下面的场景,我们有一个适用于许多不同场景的pod容器类型:

struct vec2 {
float x, y;
};

其中一些场景可能存储速度、位置、加速度等。现在假设我们希望能够独立处理所有这些场景,同时使类型系统工作,并维护vec2的语义,即velocity.xacceleration.y

struct Simulation {
template<typename T>
static void handle() { fprintf( stdout, "Generic handlern" ); }
};
template<>
void Simulation::handle<vec2>() { fprintf( stdout, "generic vec2 handlern" ); }
template<>
void Simulation::handle<position>() { fprintf( stdout, "position handlern" ); }
template<>
void Simulation::handle<velocity>() { fprintf( stdout, "velocity handlern" ); }
template<>
void Simulation::handle<acceleration>() { fprintf( stdout, "acceleration handlern" ); }

在上述情况下,使用typedefusing将无法完成任务,因为根据标准,它们不会影响别名的typeid,因此不能执行以下操作:

using position = vec2;

下一个尝试可能是尝试从pod继承,即:

struct position : public vec2 {}

然而,这具有的缺点是newdelete现在被破坏,因为pod类型上没有虚拟析构函数,并且position作为pod的资格也由于继承而丢失。

然后可以说,简单地复制和粘贴vec2的代码并将其重命名为所需类型就可以满足所有要求,但这也有几个问题:

  1. 复制粘贴代码不正确*
  2. 在上面的例子中,vec2没有相关的运算符或类似的东西,但任何有用的vec2类都肯定会有这个,在这种情况下,在重命名数据结构时复制和粘贴将非常容易出错,尤其是在其中一个运算符需要修复的情况下

vec2也可以封装在新型中

struct position {
vec2 pos;
};

但是这个解决方案打破了维护语义的要求。

另一件需要注意的事情是,我们可能无法控制vec2的实现(即,在使用类似GLM的库的情况下(。

我觉得模板应该提供必要的解决方案,但无法确定它的工作方式。因此,问题是重新定义类型的正确方法是什么,同时保持类型的语义,但最终使用不同的类型id?

*-不是在所有情况下,但这一次肯定是

也许是这样的。

template <typename Tag>
struct vec2 {
float x, y;
};
using position = vec2<struct PositionTag>;
using velocity = vec2<struct VelocityTag>;

positionvelocity将具有相似的行为,但是是不同的类型。

您可以将vec2定义为模板类,并使用枚举标志来表示其存储类型。

enum class data_type {
position, velocity, acceleration
};
template<data_type>
struct vec2 {
float x, y;
};
vec2<data_type::position> p;
vec2<data_type::velocity> v;
vec2<data_type::acceleration> a;

最新更新