C++ 内部 class; "nm -C" 输出中没有符号

C++ inner class; no symbol in "nm -C" output

我正在研究 gcc 4.8.1 在 Linux 上使用选项 -frepo 进行 C++ 模板实例化的细节。据我了解,此选项会对模板实例化进行一些内部清理,因此每个实例化仅在链接的二进制文件中出现一次,即使它在多个翻译单元中隐式实例化也是如此。具体上下文请参考这些示例文件:

// file: template.h
template <typename T>
class Box {
public:
    void func (const T & t) {}        // member function

    template <T t>
    T func_tmpl () { return t; }      // member function template

    template <T t>
    class inner {                     // inner class template
    public:
        const static T value = t;
    };
};

// file: main.cpp
#include "template.h"

int main (int argc, char * argv[]) {
    Box<int> b;
    b.func(3);                        // member function invocation
    int x = b.func_tmpl<7>();         // member function temple instantiation
    Box<int>::inner<5> g;             // inner class template instantiation
    int y = g.value;
    return 0;
}

当我编译 (g++ -frepo -c main.cpp) 然后检查符号 (nm -C main.o) 时,我发现:

0000000000000000 T main
                 U Box<int>::func(int const&)
                 U int Box<int>::func_tmpl<7>()

如您所料,funcfunc_tmpl 被列为未定义的符号。我不清楚的是为什么 inner 也没有列出;它在 class 模板中定义,本身就是一个 class 模板,并在 main.cpp 中实例化。谁能提出 inner 未包含在 main.o 符号中的原因,定义与否?

编译器发现Box<int>::inner<5>::value是一个常量,目标代码生成将其取出并用文字5替换了名称。如果您观察生成的汇编代码,您可能会看到如下内容:

    movl    , -12(%rbp)
    leaq    -12(%rbp), %rdx
    leaq    -13(%rbp), %rax
    movq    %rdx, %rsi
    movq    %rax, %rdi
    call    _ZN3BoxIiE4funcERKi
    leaq    -13(%rbp), %rax
    movq    %rax, %rdi
    call    _ZN3BoxIiE9func_tmplILi7EEEiv
    movl    %eax, -4(%rbp)
    movl    , -8(%rbp)

对应调用Box::func,然后调用Box::func_tmpl赋值给x,然后赋值给y。请注意,对 y 的赋值使用文字值 5.

要使符号出现在您的 nm 输出中,请使用成员本身,而不是其值。例如,存储它的引用:

    const int &y = g.value;