显式类模板实例化的链接

时间:2015-05-29 06:30:05

标签: c++ templates c++11 linkage

在不同的编译单元中是否允许同一类模板的多个实例具有相同的类型?那么功能模板呢?

示例代码如下:

test.hpp

template <typename T>
class A
{
    public:
        T out();
};

template <typename T>
T A<T>::out()
{
    return T(1);
}

test1.cpp

#include "test.hpp"
template class A<int>;
int testFn()
{
    return A<int>().out();
}

测试2.cpp

#include "test.hpp"
template class A<int>;
extern int testFn();
int main()
{
    return testFn() == A<int>().out();
}

如果我跑

g++ -std=c++11 test1.cpp test2.cpp -o test

它编译时没有抱怨重复的定义。

我正在参考标准[1] [2]的旧草案,并假设链接部分不会改变太多(匿名命名空间除外)。类模板具有3.5p4和14p4的外部链接。如果是这种情况,我希望g ++应该抱怨A :: out()的重复定义。我在这里错过了什么吗?

如果test.hpp定义了一个没有“静态”或“内联”的函数模板,该怎么办?

谢谢。

[1] http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2008/n2798.pdf [2] http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2012/n3337.pdf

1 个答案:

答案 0 :(得分:2)

在实施中找到这些问题的答案的好方法是使用&#34; nm。&#34;如果将nm的输出传递给c ++ filt,通常,受损的C ++符号更易读。

例如,如果您使用&#34; -c&#34;制作每个编译单元的&#34; .o&#34;然后你可以运行nm。当我这样做时,我发现模板成员是弱符号&#34; W&#34;代码(在x86 linux上)。这意味着多个定义是可以的,并且以某种特定于系统的方式。如果我创建一个非模板化的函数,它将显示为&#34; T&#34;在两个翻译单元中对应的目标文件。这将导致多重定义的符号。

通常,C ++模板会根据需要进行实例化(没有完整的实例化),除了声明头之外,还允许使用_impl类型的头。

您实际上不允许将成员模板定义为静态(这会产生错误)。您可以将其定义为内联。在这种情况下,您将看不到使用nm的成员模板的任何符号,因为它已内联。