为什么C++不能更轻松地对类型进行编译时查询?

Why doesn't C++ make it easier to make compile time queries on types?

本文关键字:编译 查询 类型 不能 C++ 为什么      更新时间:2023-10-16

我刚刚开始学习允许查询类型的模板元编程技巧。

例如,SFINAE允许我们在编译时通过使用重载和返回类型sizeof比较来检查类型是否具有特定的typedef或函数。

Q:那么,为什么语言不提供更好的机制/接口来进行关于类型的查询呢?

编辑:我想澄清一下,这不是咆哮(如果听起来是这样,我很抱歉)。由于我才刚刚开始欣赏模板的力量,我想确保我的思维过程不会一团糟。

对于我想要进行这些查询的每个模板类/函数,我必须创建一个特定于SFINAE的版本。一个单独的接口询问编译器"t有一个名为A的成员吗"或"t有函数<return type> (arg list)吗"不是一种更干净的方式吗?当然,编译器拥有与用户定义类型相关的所有知识——它只需要将这些知识公开给程序员进行编译时查询。

问:依赖这种通用功能是设计/思考模板的一种糟糕方式吗?如果是这样的话,请说明你的原因(如果可能的话,举几个例子来完成不查询的任务)。

模板元编程,SFINAE技巧&公司实际上并不是为做这件事而设计的。C++中的模板元编程是最早发现的。

模板一开始只是作为编写类型泛型代码的手段,增加了更多的功能来覆盖角落的情况(SFINAE的诞生是为了避免在同一程序中提取不相关的模板时可能发生的编译器错误),然后有一天有人发现C++模板提供了一种图灵完全元语言,允许执行关于类型的查询,在编译时执行计算等等。

所以,C++中的模板元编程很难理解,很难编写,很难调试,很难编译,因为它主要是对其他用途的滥用。模板只是碰巧很强大,但实际上没有人为此设计模板。

C++11为这种用法提供了一些库支持(以及一些核心语言支持),但这并不能改变这种情况的本质。

此外,如果你想听听我的意见,模板元编程目前被严重滥用;有了它,你可以建造像Boost这样的怪物。精神,但你可能不应该。

SFINAE感觉像是一个黑客,因为它确实是。你想做的是反思。

现在一开始听起来很容易,但基本问题在于一个简单的问题:你如何知道任意对象是什么类型?

在具有知道所创建的每个对象的VM/运行时的语言中,这可以通过直接询问运行时/VM来解决。在C++中,模板恰好为您提供了一个转义路径,因为在的某个点,必须实例化模板。在实例化时,编译器必须知道类型。SFINAE的主要目的是在编译时捕获这些知识,并将其重新用于编码指令,当在运行时进行评估时,这些指令将产生正确的结果,以确定实例化模板的类型。

SFINAE也恰好不需要在编译器最初不需要实现的"普通"C++模板之上添加任何额外的机制。

为了在编译时进行正确的反射,而不需要像SFINAE这样的技巧,对于一个没有外部依赖关系的静态链接程序,只需要解决停止问题。这是明智的人、编译器作者甚至语言委员会都非常希望避免的事情。

为了在一般情况下做到这一点,包括编写库代码,这些代码将来将作为DSO被其他代码链接。。。好吧,你必须做时间旅行到未来,只是为了检查未来的代码。所以,是的,这是不可能的。

因此,您需要有关类型和方法的适当运行时信息,以便执行您真正想要执行的操作。但是SFINAE为您提供了一个快捷方式,因为您可以使用在实例化时传递类型的事实来提取信息,使用模板中的类型变量和编译时评估的大小来将编译时类型变量导出为生成代码中的常量,这是模板实例化的副作用。正如所说,它之所以感觉像是一个黑客,是因为它是一个。