【发布时间】:2014-08-28 15:20:39
【问题描述】:
std.conv.to!string(enum.member) 是如何工作的?一个函数怎么可能接受一个枚举成员并返回它的名字?它是否使用编译器扩展或类似的东西?自从我来自 C/C++ 世界以来,这对我来说有点平常。
【问题讨论】:
std.conv.to!string(enum.member) 是如何工作的?一个函数怎么可能接受一个枚举成员并返回它的名字?它是否使用编译器扩展或类似的东西?自从我来自 C/C++ 世界以来,这对我来说有点平常。
【问题讨论】:
它的作用是使用枚举类型的编译时反射来获取成员列表(名称为字符串)及其值。它根据这些信息构造一个 switch 语句,以便快速查找以从值中获取名称。 to!SomeEnum("a_string") 使用相同的原理,只是方向相反。
使用__traits(allMembers, TheEnumType) 访问编译时反射信息,它返回一个字符串列表,可以循环访问以构建switch 语句。然后__traits(getMember, TheEnumType, memberName) 用于获取body。
特征可以在这里看到更多:http://dlang.org/traits.html#allMembers
allMembers 可用于多种类型,不仅适用于示例中的类,还适用于结构、枚举等,甚至模块。
火卫一源代码有一些例子,如EnumMembers in std.traits: https://github.com/D-Programming-Language/phobos/blob/master/std/traits.d#L3360
虽然 phobos 源有点难以阅读,但在第 3399 行,在该函数的底部,您可以看到它使用 __traits(allMembers) 作为其数据源。 std.conv.to 由许多 std.traits 函数实现。
您还可以查看示例章节选项卡,从我的 D 食谱中获取反射章节,该章节也讨论了这些内容:
http://www.packtpub.com/discover-advantages-of-programming-in-d-cookbook/book
那一章的最后一个例子展示了如何使用几种反射能力来构建一个基于字符串的小函数调度器。下一章(虽然不是免费的)展示了如何用它来构建一个交换机以提高效率。这实际上很简单:只需将 case 语句放在 foreach 中的编译时数据上,D 编译器就会展开然后为您优化查找表!
【讨论】: