正确的“多态性”方式来存储枚举和有时一些数据 [英] Correct "polymorphic" way to store an enum and sometimes some data

查看:161
本文介绍了正确的“多态性”方式来存储枚举和有时一些数据的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我在一个程序,我存储一个 std :: vector 的点,我还加载一个 std :: unordered_map ofconstraints,然后将其应用到点数组。目前的约束形式如下:

I'm working on a program for which I store an std::vector of points, I also load an std::unordered_map of "constraints" for some of these points, and then apply it to the array of points. Currently the constraints are of the form:

+---------------+
|Type    |Value |
+---------------+
|Constant|  1.0 |
|        |      |
|Lerp    |  n/a |
|        |      |
|Loop    |  n/a |
|        |      |
|...     |      |
+--------+------+

有几种类型,但只有其中一个(Constant)实际上需要存储一个值(在这种情况下为double)。在原型中,我选择存储所有类型的值,并使用 std :: pair< ConstraintType,double> 。它工作,但感觉不好;而常数是最常见的点类型,存储甚至几千未使用的双打在现代硬件上是可以忽略不计的,我不喜欢浪费。但我不能想出一个更好的方法。如果我从一个基类派生,只要我能看到,我将最终得到一个基类与一个虚拟方法(你的派生类型是什么?),然后如果它是常量我downcast它,并获得值。 Yuck。我想到的唯一的另一个想法只是将常量保存在一个单独的 std :: unordered_map ,但是如果我添加另一个约束需要值(或两)?它似乎不按比例。

There are several types, but only one of them (Constant) actually needs to store a value (in this case a double). In the prototype I chose to store the value for all of the types and just used a std::pair<ConstraintType, double>. It works, but it feels bad; while Constant is the most common point type and storing even a few thousand unused doubles is fairly negligible on modern hardware I don't like the wastefulness. I can't however think of a better way of doing it. If I derive from a base class, as far as I can see, I'm going to end up with a base class with a single virtual method (what's your derived type?) and then if it's constant I downcast it and get the value. Yuck. The only other idea I'm thinking of is just to hold the constants in a separate std::unordered_map, but what then do I do if I add another constraint that requires a value (or two)? It doesn't seem to scale.

我肯定在这里缺少一些东西,这种事情应该是微不足道的。

I'm surely missing something here, this sort of thing should be trivial. Advice would be gratefully accepted (I'm sure it will be a headdesk moment).

推荐答案

您可以将多态类存储为一个指针(例如unique_ptr),但是你没有多少(因为那将有4或8个B指针和另一个4-8 B指针到虚拟表,所以至少额外8 B在32位app是相同的,每次存储double,它会慢于)

You could store the polymorphic class as a pointer (unique_ptr for example), but then you don't gain much (as there will then be 4 or 8 B for pointer and another 4-8 B pointer to the virtual table, so at least extra 8 B on 32-bit app which is the same as to store the double every time, and it will be slower then).

对于支票,你可以这样做没有downcasting通过提供一个(纯)虚拟bool检查(const Point&)方法或类似方法,它将以多态方式检查约束(因此约束类型可以包含任何东西并且将被适当地检查)。

As for the check, you can do that without downcasting by providing a (pure) virtual bool check(const Point &) method or similar, which will polymorphically check the constraint (so the constraint type can contain anything and will be checked appropriately).

我也认为你可以使用boost :: any或boost :: variant,但不幸的是不会帮助太多。 boost :: any使用类型擦除来保存类型,因此有一个指向虚拟持有者的指针(它还有一个指向虚拟表的指针)。

I was also thinking that you could use boost::any or boost::variant, but that unfortunately wouldn't help much. boost::any uses type erasure to hold the type, so there is a pointer to a virtual holder inside (which again has a pointer to virtual table).

boost: :variant需要知道所有类型的预先,这可能适用于这里。但是boost :: variant里面的存储空间必须和它能容纳的最大类型一样大(所以没有改进,因为每个实例基本上需要和存储double的最大约束相同的空间)。但是,boost :: variant的一个优点是,可以通过使用boost :: static_visitor而不需要虚拟运行时分派来进行检查,因此它会更快。

boost::variant requires to know all the types upfront, which might be applicable here. However the storage inside the boost::variant must be as big as the largest type it can hold (so no improvement, as each instance would basically require the same space as the largest constraint storing the double). However, one advantage of boost::variant would be that the check can be done without virtual runtime dispatch, by using boost::static_visitor, so it is faster then.

一般来说,为了真正保存最大的空间量,我没有看到任何更好的选择比保持不同的约束类型(根据大小)在不同的列表。第二个最好的选择是IMHO使用boost :: variant,但是使用指针(特定的约束类型不需要是多态的,所以你节省了指向虚拟表的指针所需的空间)。

In general, to really save the maximum amount of space, I don't see any better option than to keep the different constraint types (according to size) in different lists. Second best option is IMHO to use boost::variant, but with pointers (the particular constrain types do not need to be polymorphic then, so you save the space needed for the pointer to the virtual table).

这篇关于正确的“多态性”方式来存储枚举和有时一些数据的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆