我能否获得正式而非实际模板参数的字符串表示?

3
假设我有以下内容:
class Foo { };
template <typename T> class Bar { };
template <typename NiftyType> class Baz { };

在现代(ish)的C++中,我可以使用:
typeid(Foo).name()  // to will produce "Foo", or
typeid(Bar<int>).name() // to produce "Bar<int>"

但是最后一行给了我实际的模板参数;我需要形式上的。也就是说,我希望能够这样说:

magic<Bar<int>>(); // to produce "Bar<typename T>" or just "T", and
magic<Baz<int>>(); // to produce "Bar<typename Nifty>" or just "Nifty"

我能以某种方式做到这一点吗?

(显而易见的)注释:

  • 不仅限于类。
  • 我无法检测类型(如果您对此要求感到不满意,请假设这不是我的代码)。但是,可以使用某种混入类的部分解决方案。
  • 我不想手动将适当的字符串编写到某个映射中。

如果我没记错的话,你可以参考一些编译器特定的_demangle()函数,但没有标准。 - πάντα ῥεῖ
typename 参数的名称在每个翻译单元的每个声明中是否需要相同?我不认为这些信息中的任何一个在运行时被保留。为什么要保留?也许作为编译器特定的扩展,但几乎肯定不是标准所必需的。 - 5gon12eder
@5gon12eder:至于“为什么要这样做”——它对于调试非常有用... - einpoklum
2
GCC的__PRETTY_FUNCTION__会扩展成像void Baz<Nifty>::foo() [with Nifty = float]这样的东西,但我不认为那会对你有所帮助。你必须在类体中扩展该宏,而你又说你不想这样做。 - 5gon12eder
@5gon12eder:嗯。但是我可以编写一个接受Baz参数的函数,在那里完成这项工作,也许会更好。 - einpoklum
显示剩余2条评论
1个回答

1
如何?
class Foo { };
template <typename T> class Bar {
  static const char * debug_name() { return "Bar<typename T>"; }
};
template <typename NiftyType> class Baz {
  static const char * debug_name() { return "Baz<typename NiftyType>"; }
};

然后你可以像这样定义magic
template <typename T>
struct magic {
  operator const char * () { return T::debug_name(); }
};

并按照您想要的方式使用它。
int main() {
  magic<Bar<int>>();
  magic<Baz<int>>();
}

我认为,基于我的C ++经验,要求编译器为您生成debug_name相当乐观。 C ++是一种好用的语言,但内省绝对不是它的长处,而且你正在要求内省一个模板,而不仅仅是一个类型。
请注意,如果强制编译器支持您所要求的作为内置功能,它将有效地禁止编译器解析模板定义并丢弃(不相关的)模板参数的标识符名称,并仅存储模板定义的解析AST形式,这可能会减少内存使用。或者它可能必须对源代码进行第二次遍历以再次获取名称或进行某些可怕的操作。
我认为有一些比您所要求的远不那么雄心勃勃的事情是不可能的,或者只能使用各种编译器特定扩展来实现。希望有所帮助。

我的意思是你可以使用宏来避免重复,但代价是什么...我从未说过这些都是好主意,只是OP想要的:p - Chris Beck
嗯,显然我是指不需要我手动添加类型或自己编写字符串... - einpoklum
1
嗯,正如我所解释的那样,“magic”并不是标准的一部分,所以如果你也不愿意自己生产它,那么显然不会发生。我的意思是,你可以像其他人一样轻松地查找标准中的“typeinfo”功能。 - Chris Beck
请注意,即使这不是“您的代码”,您仍然可以通过创建一个类型特征来保存调试字符串并将其放在自己的头文件中来实现此目的。如果您不想自己编写字符串,您可以在编译器之外制作一个单独的工具,并将其作为构建系统的一部分从 xml 规范生成调试字符串... - Chris Beck

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