问题 自动计算TMP中实例化类的数量?


给定模板元程序(TMP),C ++编译器是否会生成构建统计信息,以计算实例化类的数量?或者有没有其他方法可以自动获取此号码?所以对于例如对立的因子

#include <iostream>

template<int N> struct fact { enum { value = N * fact<N-1>::value }; };
template<> struct fact<1> { enum { value = 1 }; };

int main()
{
    const int x = fact<3>::value;
    std::cout << x << "\n";
    return 0;
}

我想回到3号(因为事实<3>,事实<2>,事实<1>被实例化)。这个例子当然是微不足道的,但每当你开始使用例如Boost.MPL,编译时间真的爆炸了,我想知道有多少是由于隐藏的类实例化。我的问题主要是针对Visual C ++,但是gcc的答案也会受到赞赏。

编辑:我目前非常脆弱的Visual C ++方法是添加Stephan T. Lavavej之一的编译开关 视频 / d1reportAllClassLayout并对输出文件执行grep +字数计数,但它(a)极大地增加了编译时间,并且(b)正则表达式很难100%正确。


10105
2017-07-09 21:26


起源



答案:


我制造了一个 一线改变 到GCC,它使它在实例化时打印出每个类模板的名称。您已经可以调用C ++前端了 cc1plus 直接没有 -quiet 用于获取功能模板的标志。

我还没有把它变成一个合适的GCC选项,它只是我自己的源代码树上的黑客攻击。我正在考虑将其作为插件实现,但它并不是我的TODO列表的顶部。


8
2017-07-09 22:33



+1。我建议攻击任何开源编译器都应该很容易,但实际上你已经以最好的方式证明了这一点(通过编写一个实际执行它的补丁)。 - abarnert
谢谢!甚至更方便的是(是的,范围蠕变即将出现!)是所有类模板的日志和它们的实例化的数量,而不仅仅是所有实例化的总数或整个列表。也许用于后处理完整构建日志的perl脚本是我应该尝试的。 - TemplateRex
只需将输出传递给 awk -F '<' '{ templates[$1]++ } END { for (t in templates) print t, templates[t] }' - Jonathan Wakely


答案:


我制造了一个 一线改变 到GCC,它使它在实例化时打印出每个类模板的名称。您已经可以调用C ++前端了 cc1plus 直接没有 -quiet 用于获取功能模板的标志。

我还没有把它变成一个合适的GCC选项,它只是我自己的源代码树上的黑客攻击。我正在考虑将其作为插件实现,但它并不是我的TODO列表的顶部。


8
2017-07-09 22:33



+1。我建议攻击任何开源编译器都应该很容易,但实际上你已经以最好的方式证明了这一点(通过编写一个实际执行它的补丁)。 - abarnert
谢谢!甚至更方便的是(是的,范围蠕变即将出现!)是所有类模板的日志和它们的实例化的数量,而不仅仅是所有实例化的总数或整个列表。也许用于后处理完整构建日志的perl脚本是我应该尝试的。 - TemplateRex
只需将输出传递给 awk -F '<' '{ templates[$1]++ } END { for (t in templates) print t, templates[t] }' - Jonathan Wakely


当然,没有可移植的方法来做到这一点。

对于大多数编译器来说,有很多方法可以做到这一点。你已经为MSVC找到了一个。对于gcc,你可以使用gccxml。或者,对于任何开源编译器(gcc或clang),在实例化时添加代码应该非常简单,这些代码要么保持计数,要么记录在编译完成后可以过滤的内容。

对于Clang / LLVM,你可以构建一个挂钩实例的插件,这个实例更清晰,但实际上可能更多。

带有调试符号,没有优化,没有剥离的构建可能最终会出现每个实例化的错位名称,您可以使用这些名称。但是,一些编译器(包括gcc)总是至少内联一些方法,无论你是否想要它们。如果您愿意修改代码,可能会强制它生成外部实例化,可能是这样的:

template<int N> struct fact { 
  enum { value = N * fact<N-1>::value }; 
  int *dummy() { return &fact<N-1>::value; }
};

2
2017-07-10 00:03



谢谢!修改代码实际上不是一个选项,因为99%的实例化类模板来自Boost.MPL和<type_traits>等,我想要清楚计算这些。 - TemplateRex
我相信MSVC可以设置为完全关闭所有内联和优化,这意味着您将获得所有内容的外部实例化,但我不认为任何其他编译器具有此类设置。 - abarnert


Steven Watanabe编写的工具可用于计算模板实例的数量。你可以得到它 这里。基本上,它修改代码,以便每次实例化类时都会生成编译器警告,然后您可以使用正则表达式处理生成的文本。


1
2017-07-11 12:55



谢谢,我试试看。 - TemplateRex