【问题标题】:Automatically count the number of instantiated classes in a TMP?自动计算 TMP 中实例化类的数量?
【发布时间】:2012-07-09 21:26:29
【问题描述】:

给定一个模板元程序 (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(因为 fact、fact 和 fact 已实例化)。这个例子当然是微不足道的,但是每当你开始使用例如Boost.MPL,编译时间真的爆炸了,我想知道其中有多少是由于隐藏的类实例化。我的问题主要是针对 Visual C++,但对于 gcc 的答案也将不胜感激。

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

【问题讨论】:

    标签: c++ templates counter instantiation template-meta-programming


    【解决方案1】:

    我给 GCC 写了一个one-line change,让它在实例化每个类模板时打印出它的名称。您已经可以在没有 -quiet 标志的情况下直接调用 C++ 前端 cc1plus 以获得相同的函数模板。

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

    【讨论】:

    • +1。我建议破解任何开源编译器应该很容易,但您实际上以最好的方式证明了这一点(通过编写实际执行它的补丁)。
    • 谢谢!更方便的是(是的,范围蔓延!)是所有类模板及其实例化数量的日志,而不仅仅是所有实例化的总数或整个列表。也许我应该尝试一个用于后处理完整构建日志的 perl 脚本。
    • 只管输出到awk -F '&lt;' '{ templates[$1]++ } END { for (t in templates) print t, templates[t] }'
    【解决方案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; }
    };
    

    【讨论】:

    • 谢谢!修改代码并不是一个真正的选择,因为 99% 的实例化类模板来自 Boost.MPL 和 等,我也希望对这些模板进行清点。
    • 我相信 MSVC 可以设置为完全关闭所有内联和优化,这意味着您将获得所有内容的离线实例化,但我认为任何其他编译器都没有这样的设置.
    【解决方案3】:

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

    【讨论】:

      猜你喜欢
      • 2017-02-26
      • 2014-10-24
      • 2011-08-04
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2022-11-26
      • 2010-11-26
      相关资源
      最近更新 更多