如何在编译时查询一个类的所有基类?

3
使用std::is_base_of<A,B>::value可以检查类A是否是类B的基类。但是是否有可能查询编译器获取类B的所有基类,例如base_classes_of<B>返回一个包含所有基类的std::tuple? 是否在g ++中存在非标准扩展程序可以完成此操作?
如果根本不可能,请问有人知道为什么吗?这听起来像是编译器很容易拥有的一个相当基本的信息。
示例:
#include <type_traits>
#include <tuple>

struct A {};
struct B : A {};

static_assert(std::is_base_of<A, B>::value, "A is base of B");
static_assert(! std::is_base_of<B, A>::value, "but B is not base of A");

// now I am looking for something like
// typedef base_classes_of<B>::type B_bases;
// static_assert(std::is_same<B_bases, std::tuple<A>>::value, "all bases of B are: A");

int main() {}

@Bo Persson 我的意思是元组类型,元组类型仅存储类型序列。如果您手动使用std::tuple<A>填充B_bases,则上面的代码将正常工作。 - Lars
您可能会注意到,在您所能做的(测试已知类是否为父类)和您想要做的(查找基类是什么)之间存在很大差距。也许为了填补这个差距,首先需要弄清如何找到一个类的直接父类(如果可能的话)。 - UncleBens
@UncleBens 如果你有一个可以立即获取所有基类的谓词,那么编写一个迭代收集所有基类的谓词就很简单了。但是看起来这也不可能?所以为什么会这样是很有趣的呢? - Lars
@Alexandre C. 谢谢。请看我下面对 paul_71 的回答。 - Lars
1
@Lars: 仅供参考,basesdirect_bases是在N2965中提出的。我认为在某些情况下存在对类似于bases的编译时查询的需求。然而,不幸的是,当前的C++还缺少这一功能。 - Ise Wisteria
显示剩余6条评论
3个回答

2

N2965中提出了类似的basesdirect_bases设施。
对于数据成员,由于数据成员可以是位域,它们的类型特征有一些微妙之处。
另一方面,基类没有这样的问题。
我认为在某些情况下有一些编译时查询的需求,比如在N2965的动机示例中提到的bases
然而,不幸的是,当前的C++还缺乏这个功能,就我所见,GCC和Clang-C++目前似乎也没有提供类似的设施...


1

不,标准C++中不可能实现这一点,但是为了您的预期目的,您可以使用单独的断言,每个基类需要存在一个(或者将其包装在类型列表中)。

祝好!


1

无法查询给定类型的基本类型的C++程序 - 实际上无法查询C++程序的任何内容... 但是,您可以编写一个元谓词,将已知类型与已知类型的类型列表(或参数包)进行查询(或反之),并在编译时生成真实或虚假类型 - 它只会递归应用std::is_base_of元谓词到参数包中的所有类型,并累积结果。这是我能想到的唯一方法。我可以编写一些执行此操作的代码,但我怀疑这不是您真正想要的。真正的问题是:为什么您需要这样做,或者更好的说,为什么您需要在C++中这样做?


谢谢。如何对类型列表迭代地应用std::is_base_of是很直接的。我只是好奇为什么你可以为较弱的查询(is_base_of)编写元谓词,但不能为更强的查询(base_classes_of)编写元谓词,因为(a)编译器已经有了这个信息,而且(b)基类列表似乎是关于一个类的基本信息。我认为可能有比“没有人需要这个信息”更强的理由(特别是在许多其他语言(如Java)中,您可以获得基类)。 - Lars
好吧,关键是像Java这样的“语言”完全不同。我在引号中放置了“语言”,因为使您能够做到这一点的不是语言,而是编写这些语言的运行时。托管程序由程序流本身(翻译为中间语言)和程序使用的类型的元信息组成。执行时,此数据会被即时编译为二进制代码,然后由底层平台执行...继续... - Paul Michalik
继续...二进制代码中没有留下任何元信息 - 它只是愚蠢地执行它被告知要执行的内容。现在来到了关键点:C++程序立即编译成二进制代码 - 从中无法检索到这种信息。唯一拥有类型及其关系信息的人是C++编译器,因此您可以在编译时查询此类关系。嗯,准确地说,这些“查询”基于语言的某些边缘特征,因此我不会真正将它们视为查询... - Paul Michalik

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接