打印任意 C++ 的类型表达式
我有兴趣编写一个用于教学目的的工具,用于评估 C++ 表达式并打印其类型。本质上,我的想法是我的学生可以输入任何表达式,程序将回显表达式的类型。是否有现有的工具可以做到这一点?如果没有,是否有一种非常简单的方法可以通过与现有编译器集成并调用其调试器或 API 来实现?例如,有人告诉我,Clang 有一个相当完整的编译器 API,也许有某种方法可以将字符串与适当的包含指令一起传递到 Clang 中,并让它吐出一个类型?
我意识到,如果目前还没有类似的项目,这可能是一个巨大的项目。我只是认为它具有重要的教育价值,所以看起来值得检查。
I'm interested in writing a tool for teaching purposes that evaluates C++ expressions and prints their types. Essentially, my thinking is that my students could type in any expression, and the program would echo back the type of the expression. Is there an existing tool that already does this? If not, is there a pretty easy way to do it by integrating with an existing compiler and calling into its debugger or API? I've been told, for example, that Clang has a fairly complete compiler API, perhaps there's some way to just pass a string into Clang along with the appropriate include directives and have it spit out a type?
I realize that this is potentially a huge project if there's nothing close to this existing today. I just thought it would have significant educational value, so it seemed like it was worth checking.
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(4)
受本·沃伊特评论的启发,我想出了一个答案。只需创建一个错误,然后让编译器告诉您导致该错误的类型:
结果:
另外,因为您只执行编译器,你很安全。确实不需要沙箱。如果您得到除“对
void foo(T)
的未定义引用”以外的任何内容,则它不是表达式。[编辑] 你会如何将其放入工具中?简单,使用宏
现在使用
$(CC) /D=(EXPR) TestHarness.cpp
进行编译。使您不必每次都重建输入文件。I came up with an answer inspired by Ben Voigt's comments. Just make a bug and let the compiler tell you the type which caused it:
Result:
Also, since you execute nothing but the compiler, you're pretty safe. No sandboxing needed, really. If you get anything other than "undefined reference to
void foo<T>(T)
", it wasn't an expression.[edit] How would you put this into a tool? Simple, with macro's
Now compile with
$(CC) /D=(EXPR) TestHarness.cpp
. Saves you from rebuilding the input file every time.进一步改进 MSalter 的改进:
结果(使用
$user_code = "1 + 3.0"
):这避免了链接步骤。
原始答案:
C++ 有
typeid
关键字。从概念上讲,您只需将用户的表达式粘贴到一些样板中,例如:然后将该源文件传递给编译器,并运行它以获得答案。
实际上,很难避免运行恶意代码。您需要使用某种类型的沙箱。或者要非常小心,确保没有不匹配的括号(你确实知道什么是三字母,对吧?)。
更好的选择是避免运行该程序。使用如下框架(需要 C++11):
您可以使用以下选项运行编译器生成调试数据,然后使用例如 dwarf2 读取器库并获取与
the_value
关联的符号类型信息,然后删除一级指针。Improving yet more on MSalter's improvement:
Result (with
$user_code = "1 + 3.0"
):This avoids the link step.
Original answer:
C++ has the
typeid
keyword. Conceptually, you just need to stick the user's expression into some boilerplate like:And then pass that source file to the compiler, and run it to get the answer.
Practically, it's going to be difficult to avoid running malicious code. You'd need to use a sandbox of some type. Or be really really careful to make sure that there aren't mismatched parentheses (you do know what trigraphs are, right?).
A better option would be to avoid running the program. With a framework (requires C++11) like:
You could run the compiler with the option to generate debug data, then use e.g. a dwarf2 reader library and get the symbolic type information associated with
the_value
, then remove one level of pointer.以下是在 GCC 和 Clang 中使用
__PRETTY_FUNCTION__
执行此操作的一种方法:输出关于海湾合作委员会:
Here's one way you can do this in GCC and Clang with
__PRETTY_FUNCTION__
:Output on GCC:
如今,有一种这样的工具——在线。但它只是作为一个意想不到的副产品做你想做的事情。我说的是 Matt Godbolt 的编译器资源管理器。
您的“程序”将如下所示:
现在,如果您将
123
替换为 C++ 表达式,您将 get,在编译器错误消息部分,如下:第一行有您想要的类型,位于尖括号内。
These days, there sort of is such a tool - online. It only does what you want as an unintended by product though. I'm talking about Matt Godbolt's Compiler Explorer.
Your "program" will look like this:
Now, if you replace
123
with a C++ expression, you'll get, in the compiler error messages section, the following:The first line has your desired type, within the angle brackets.