10

给定模板元程序(TMP),C++编译器是否会生成构建统计信息来计算实例化类的数量?或者有没有其他方法可以自动获得这个数字?因此对于例如所述obiquitous阶乘自动计算TMP中实例化类的数量?

#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++从斯蒂芬T. Lavavej的videos/d1reportAllClassLayout之一加入编译开关,这样做对输出文件的grep +字数,但它(一)增加编制我目前非常脆弱的方法次数巨大和(b)正则表达式很难100%正确。

回答

7

我向GCC做了一个one-line change,它使得它在实例化时打印出每个类模板的名称。您可以直接调用C++前端cc1plus而不使用-quiet标志以获得相同的函数模板。

我还没有想到将其转化为适当的GCC选项,但它只是对我自己的源代码树进行破解。我正在考虑将它作为插件来实现,但它并不在我的TODO列表的顶部。

+0

+1。我建议,应该很容易地破解任何开源编译器,但是实际上以最好的方式证明了它(通过编写一个实际上可以实现的补丁)。 – abarnert 2012-07-10 01:19:05

+0

谢谢!什么会更方便(是的,范围蔓延!)是所有类模板的日志和它们的实例化的数量,而不仅仅是所有实例的总数或整个列表。也许一个perl脚本来后处理完整的构建日志是我应该尝试的。 – TemplateRex 2012-07-10 06:11:58

+1

只是输出到'awk -F'<''{templates [$ 1] ++} END {for(t in templates)print t,templates [t]}'' – 2012-07-10 09:11:38

2

当然,没有便携的方式来做到这一点。

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

对于Clang/LLVM,您可以构建一个挂钩实例化的插件,该实例化更清晰,但可能实际上还有更多工作。

使用调试符号进行构建,不进行优化,并且不会剥离可能最终会出现每个实例的重名名称,您可以使用grep。不过,有些编译器(包括gcc)总是会内联至少一些方法,不管你是否希望它们。如果你愿意修改代码,你或许可以迫使它产生出来的行实例,也许是这样的:

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

谢谢!修改代码并不是一个真正的选择,因为99%的实例化类模板来自Boost.MPL和等,我也希望有一个清晰的计数。 – TemplateRex 2012-07-10 06:12:49

+0

我相信MSVC可以设置为绝对关闭所有内联和优化,这意味着您将得到一切的实例化,但我不认为其他任何编译器都有这样的设置。 – abarnert 2012-07-10 17:49:32

1

有由史蒂芬渡边写了一个工具,可以用来计数模板实例化的数量。你可以得到它here。基本上,它会修改代码,以便每次实例化类时都会生成编译器警告,然后可以使用正则表达式处理结果文本。

+0

谢谢,我会试一试。 – TemplateRex 2012-07-11 13:26:02