C ++:使用编译器API而不是C ++功能进行元编程
这最初是一个SO问题,但我意识到这是非常不合常规的,并且根据网站上的实际描述,它可能更适合程序员。因为该问题在概念上具有很大的分量。 我一直在学习clang LibTooling,它是一个非常强大的工具,能够以友好的方式(即以语义的方式,而不是通过猜测)公开代码的整个“坚韧不拔” 。如果clang可以编译您的代码,则clang 可以确定该代码内每个字符的语义。 现在让我退一步。 当人们从事C ++模板元编程时(特别是当冒险超越模板进入聪明的领域,尽管使人恐惧)时,会出现许多实际问题。老实说,对于包括我自己在内的许多程序员而言,模板的许多常规用法也有些令人恐惧。 我想一个很好的例子就是编译时字符串。这是一个已经存在一年多的问题了,但是很显然,到目前为止,C ++对于普通人来说并不容易。尽管看这些选项还不足以引起我的恶心,但我仍然对能够产生神奇的,最高效率的机器代码以适应我的软件中任何花哨的应用程序没有信心。 我的意思是,让我们面对现实吧,伙计们,琴弦非常简单和基本。我们中的某些人只是想要一种便捷的方法来发出带有某些字符串的机器代码,而这些字符串在某些情况下“嵌入”了比直接编写代码时要多得多。在我们的C ++代码中。 输入clang和LibTooling,这将公开源代码的抽象语法树(AST),并允许简单的自定义C ++应用程序正确正确地操作原始源代码(使用Rewriter)以及AST中所有对象的丰富的面向对象的语义模型。它处理很多事情。它了解宏扩展,并让您遵循这些链。是的,我说的是源代码到源代码的转换或翻译。 我在这里的基本论点是,使用clang,现在我们可以创建可执行文件,这些可执行文件本身可以用作C ++软件的理想自定义预处理程序阶段,并且可以使用C ++实现这些元编程阶段。我们仅受以下事实的约束:该阶段必须接受有效的C ++代码的输入,并产生更多有效的C ++代码作为输出。加上您的构建系统适用的任何其他限制。 输入至少必须非常接近有效的C ++代码,因为毕竟clang是编译器的前端,而我们只是在四处寻找并利用其API发挥创意。我不知道是否有任何规定可以定义要使用的新语法,但是显然我们必须开发一种方法来正确解析它并将其添加到clang项目中。期望更多的是在clang项目中超出范围。 没问题 我可以想象一些无操作宏函数可以处理此任务。 查看我正在描述的另一种方法是通过运行我们的源代码的AST(感谢clang及其API)来使用运行时C ++实现元编程构造,而不是使用语言本身可用的更有限的工具来实现它们。这也具有明显的编译性能优势(繁重的模板头与您使用它们的频率成比例地减慢了编译速度。然后,许多已编译的东西被链接器仔细地匹配并丢弃了)。 但是,这样做的代价是在构建过程中引入了额外的一两个步骤,并且还要求(当然)编写一些更详细的软件(但至少是简单的运行时C ++)作为我们工具的一部分。 那不是全部。我非常确定,生成核心语言功能极其困难或不可能的代码可以提供更大的功能空间。在C ++中,您可以编写模板,宏或两者的疯狂组合,但是在clang工具中,您可以在运行时以C ++可以实现的任何方式修改类和函数,同时可以完全访问语义内容,除了模板和宏以及其他所有内容。 因此,我想知道为什么每个人都还没有这样做。是不是来自clang的此功能如此新,并且没人熟悉clang的AST的巨大类层次结构?那不可能。 也许我只是低估了这一点的难度,但是使用clang工具执行“编译时字符串操作”几乎在犯罪上很简单。它很冗长,但是非常简单。所需要的只是一堆无操作宏函数,它们映射到实际的实际std::string操作。clang插件通过获取所有相关的无操作宏调用来实现此目的,并使用字符串执行操作。然后将该工具作为构建过程的一部分插入。在构建过程中,这些无操作宏函数调用会自动评估为其结果,然后作为纯旧的编译时字符串插入到程序中。然后可以照常编译该程序。实际上,结果是该程序的移植性也大大提高,不需要新的支持C ++ 11的编译器。