编译器构造 – 变体的转换系统

我编写了一个变体类,它将用作动态语言中的主要类型,最终将允许256种不同类型的值(标头是无符号字节,实际上只使用了20个).我现在想要在类型之间实现转换/转换.

我最初的想法是查找表,但是需要的内存剪切量使得它实现起来不切实际.

有哪些替代方案?现在我正在考虑另外三种方法来自其他人的研究和建议:

>将类型分组为更大的子集,例如数字或集合或其他.
>创建一个具有CanCast(from,to)和Cast(Variant)方法的转换接口,并允许将实现该接口的类添加到列表中,然后可以检查该列表以查看是否有任何转换类可以执行转换.
>类似于(1)但是制作了几种主类型,并且转换是从原始类型到主类型然后再到最终类型的两步过程.

什么是最好的系统?

编辑:我已经添加了赏金,因为我仍然不确定最好的系统,目前的答案是非常好的,并且肯定得到了我的1但是必须有人在那里做了这个并且可以说最好的方法是什么.

最佳答案 我的系统非常“繁重”(很多代码),但非常快,而且功能非常丰富(跨平台C).我不确定你想要用你的设计走多远,但这是我所做的最重要的部分:

DatumState – 持有“类型”的“枚举”的类,加上原生值,它是所有基本类型中的“联合”,包括void *.此类与所有类型解耦,可用于任何本机/基元类型,以及“引用”void *类型.由于“enum”还具有“VALUE_OF”和“REF_TO”上下文,因此该类可以表示为“完全包含”浮点数(或某些基本类型),或者“引用但不拥有”浮点数(或某些原语)类型). (我实际上有“VALUE_OF”,“REF_TO”和“PTR_TO”上下文,所以我可以逻辑地存储一个值,一个不能为null的引用,或一个可能为null或者指针的指针不,而且我知道我需要删除或不删除.)

Datum – 完全包含DatumState的类,但扩展其接口以适应各种“众所周知的”类型(如MyDate,MyColor,MyFileName等).这些众所周知的类型实际上存储在DatumState成员内的void *中.但是,因为DatumState的“枚举”部分具有“VALUE_OF”和“REF_TO”上下文,所以它可以表示“指向MyDate的指针”或“MyDate的值”.

DatumStateHandle – 使用(众所周知的)类型(如MyDate,MyColor,MyFileName等)参数化的辅助模板类.这是Datum用于从众所周知的类型中提取状态的访问器.默认实现适用于大多数类,但具有特定访问语义的任何类仅覆盖此模板类中一个或多个成员函数的特定模板参数化/实现.

宏,辅助函数和其他一些支持的东西 – 为了简化“添加”已知类型到我的Datum / Variant,我发现将逻辑集中到几个宏中很方便,提供一些支持函数,如运算符重载,并建立一些我的代码中的其他约定.

作为此实现的“副作用”,我获得了许多好处,包括引用和值语义,所有类型的“null”选项,以及对所有类型的异构容器的支持.

例如,您可以创建一组整数并将它们编入索引:

int my_ints[10];
Datum d(my_ints, 10/*count*/);
for(long i = 0; i < d.count(); ++i)
{
  d[i] = i;
}

类似地,一些数据类型由字符串或枚举索引:

MyDate my_date = MyDate::GetDateToday();
Datum d(my_date);
cout << d["DAY_OF_WEEK"] << endl;
cout << d[MyDate::DAY_OF_WEEK] << endl; // alternative

我可以存储项目集(本机)或基准集(包装每个项目).无论哪种情况,我都可以递归地“解包”:

MyDate my_dates[10];
Datum d(my_dates, 10/*count*/);
for(long i = 0; i < d.count(); ++i)
{
  cout << d[i][MyDate::DAY_OF_WEEK] << endl;
}

有人可能认为我的“REF_TO”和“VALUE_OF”语义是过度的,但它们对于“设置 – 展开”至关重要.

我用九种不同的设计完成了这个“Variant”的东西,我的当前是“最重的”(大多数代码),但是我最喜欢的那个(几乎是最快的,具有非常小的物体足迹),而且我已经我弃用了其他八种设计.

我设计的“缺点”是:

>通过访问对象
来自void *的static_cast<>()
(类型安全且相当快,但是
间接是必需的;但,
副作用是设计支持
存储“null”.)
>编译因为更长
暴露的众所周知的类型
通过Datum界面(但是你
如果不这样做,可以使用DatumState
想要知名的类型API).

无论您的设计如何,我都建议如下:

>使用“枚举”或其他东西来说明
你是“类型”,与之分开
“值”. (我知道你可以压缩
他们变成了一个“int”或者什么
有点打包,但就是这样
访问速度慢,非常棘手
维持新的类型
介绍.)
>依靠模板或某些东西集中运营,用
特定类型的机制
(覆盖)处理(假设你想要
处理非平凡的类型).

游戏名称是“添加新类型时的简化维护”(或者至少,它适合我).就像一篇好的学期论文一样,如果你不断删除维护系统所需的代码(例如,最小化调整新类型所需的工作量),那么重写,重写,重写,保持或增加功能是一个非常好的主意.到你现有的Variant基础设施).

祝好运!

点赞