【问题标题】:Can we see the template instantiated code by C++ compiler我们可以看到 C++ 编译器的模板实例化代码吗
【发布时间】:2011-05-25 18:54:47
【问题描述】:

有没有办法知道编译器在 C++ 中为模板函数或类实例化代码

假设我有以下代码

template < class T> T add(T a, T b){
            return a+b;
}

现在当我打电话时

add<int>(10,2); 

我想知道编译器为 int 特定版本创建的函数。

我正在使用 G++、VC++。如果有人能帮我指出实现这一点的编译器选项,那将会很有帮助。

希望问题很清楚。提前致谢。

【问题讨论】:

标签: c++


【解决方案1】:

Clang (https://clang.llvm.org/) 可以漂亮地打印实例化模板的 AST:

你的例子:

test.cpp

template < class T> T add(T a, T b){
    return a+b;
}

void tmp() {
    add<int>(10,2); 
}

漂亮打印 AST 的命令:

$ clang++ -Xclang -ast-print -fsyntax-only test.cpp

Clang-5.0 输出:

template <class T> T add(T a, T b) {
    return a + b;
}
template<> int add<int>(int a, int b) {
    return a + b;
}
void tmp() {
    add<int>(10, 2);
}

【讨论】:

  • 我相信这是 OP 正在寻找的最佳答案(与其他替代方案相比)。
【解决方案2】:

如果你想查看汇编输出,使用这个:

g++ -S file.cpp

如果你想查看 GCC 生成的一些(伪)C++ 代码,你可以使用这个:

g++ -fdump-tree-original file.cpp

对于您的 add 函数,这将输出类似

;; Function T add(const T&, const T&) [with T = int] (null)
;; enabled by -tree-original

return <retval> = (int) *l + (int) *r;

(我通过引用传递参数以使输出更有趣)

【讨论】:

    【解决方案3】:

    你绝对可以看到g++使用“-S”选项生成的汇编代码。

    我认为不可能显示“C++”等效模板代码 - 但我仍然希望 g++ 开发人员解释为什么 - 我不知道 gcc 的体系结构。

    使用汇编时,您可以查看生成的代码,寻找与您的函数相似的部分。由于运行 gcc -S -O1 {yourcode.cpp},我得到了这个(AMD64,gcc 4.4.4)

    _Z3addIiET_S0_S0_:
    .LFB2:
        .cfi_startproc
        .cfi_personality 0x3,__gxx_personality_v0
        leal    (%rsi,%rdi), %eax
        ret
        .cfi_endproc
    

    这实际上只是一个 int 加法(leal)。

    现在,如何解码 c++ name mangler?有一个名为 c++filt 的实用程序,您粘贴规范(C 等效)名称,您将获得解组后的 c++ 等效项

    qdot@nightfly /dev/shm $ c++filt 
    _Z3addIiET_S0_S0_ 
    int add<int>(int, int)
    

    【讨论】:

    • 如果允许人们查看生成的模板代码,无论如何阅读可能会太多......在STL的情况下
    • 好吧,人们可以看到生成的程序集,这已经很多了,但是,有时这正是您获得宝贵见解所需要的......
    • @qdot 查看程序集和 c++ 生成的代码是完全不同的。有时您想通过使用 TypeLists 来生成类的层次结构,那么您可能需要将结果作为 c++ 代码查看,以确保在您的层次结构中。在这种情况下,组装根本没有帮助。
    【解决方案4】:

    现在有一个在线工具可以为您执行此操作:https://cppinsights.io/ 例如,此代码

    template<class X, class Y> auto add(X x, Y y) {
      return x + y;
    }
    
    int main()
    {
      return add(10, 2.5);
    }
    

    被翻译成

    template<class X, class Y> auto add(X x, Y y) {
      return x + y;
    }
    
    /* First instantiated from: insights.cpp:9 */
    #ifdef INSIGHTS_USE_TEMPLATE
    template<>
    double add<int, double>(int x, double y)
    {
      return static_cast<double>(x) + y;
    }
    #endif
    
    
    int main()
    {
      return static_cast<int>(add(10, 2.5));
    }
    

    【讨论】:

    • 这应该是公认的答案。多么棒的发现!在the somewhat well-hidden About page 中,作者解释说C++ Insights 基于Clang,但它自己做了很多工作来生成比this other answer 中漂亮打印的AST 更彻底和理想的C++ 可编译的“中间”代码。它还生成诸如基于范围的for 循环之类的“原始”版本。非常令人兴奋!
    • @underscore_d 是的,我也认为它是一个很棒的工具,在某些情况下非常有用。至于接受的答案 - 是的,这对可见性很有好处,因为虽然人们可以讨论漂亮打印的 AST,但我 100% 肯定它比目前接受的 ASM 答案更好。
    【解决方案5】:

    当优化器完成它的工作时,你很可能没有任何看起来像函数调用的东西了。在您的具体示例中,您肯定会得到一个内联加法,更糟的是。除此之外,您始终可以在编译期间在单独的文件中发出生成的汇编程序,这就是您的答案。

    【讨论】:

      【解决方案6】:

      最简单的方法是检查生成的程序集。您可以通过使用 g++ 的 -S 标志来获取程序集源。

      【讨论】:

        【解决方案7】:

        如果您正在寻找等效的 C++ 代码,那么没有。编译器从不生成它。编译器直接生成它的中间表示比先生成 c++ 要快得多。

        【讨论】:

          【解决方案8】:

          我认为c++ Insights 是你想要的。

          【讨论】:

            猜你喜欢
            • 1970-01-01
            • 2014-01-16
            • 1970-01-01
            • 2018-07-08
            • 2015-07-25
            • 2013-09-11
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            相关资源
            最近更新 更多