2015-05-29 74 views
8

是否允许在不同编译单元中使用相同类型的同一类模板的多个实例化?怎么样功能模板?显式类模板实例化的链接

甲示例代码如下:

test.hpp

​​

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

+2

[temp.spec] p5 *“对于给定的模板和给定的一组模板参数, - 显式实例化定义在程序中最多只会出现一次[...]不需要实现来诊断该规则的冲突。“* – dyp

+0

参见[CWG NAD 1045](http://www.open-std.org/JTC1/SC22/WG21/docs/cwg_closed.html#1045),其中包含一个原因,这可能不诊断。 – dyp

+0

@dyp,在这种情况下,我的程序实际上违反了14.7.0.5,但标准说g ++不需要诊断,实际上g ++解决了多重定义。但为了让它符合标准,我应该只在一个翻译单元中定义所有实例,并在其他翻译单元中声明(“extern”)显式模板实例化。我对么? – nocte107

回答

1

一个好办法找到你在执行这些问题是用 “纳米”。如果将nm的输出传递给C++ filt,通常情况下,错乱的C++符号更具可读性。

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

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

你是不是真的能定义一个成员模板静态(即会给出错误)。你可以将它定义为内联。在这种情况下,您将看不到使用nm的成员模板的任何符号,因为它已被内联。

+0

在你的回答中,你提到“以某种系统特定的方式”。这是否意味着它不是由标准规定的,可能不是便携式的?至于我在函数模板上的最后一个问题,我的意思是更通用的函数模板而不是类成员函数模板。谢谢。 – nocte107