C++ 显式类模板实例化的链接

C++ 显式类模板实例化的链接,c++,templates,c++11,linkage,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); } 它编译时不会抱怨重复的定义 我参考了标准[1][2]的旧草案,并假设链接部分没有太大变化(匿名名称空间除

在不同的编译单元中是否允许使用相同类型的同一类模板的多个实例化?函数模板呢

示例代码如下所示:

test.hpp

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

template <typename T>
T A<T>::out()
{
    return T(1);
}
它编译时不会抱怨重复的定义

我参考了标准[1][2]的旧草案,并假设链接部分没有太大变化(匿名名称空间除外)。类模板通过3.5p4和14p4具有外部链接。如果是这样,我希望g++会抱怨A::out()的定义重复。我是不是遗漏了什么

如果test.hpp定义的函数模板没有“static”或“inline”,该怎么办

多谢各位

[1]
[2 ]

< P>在这些实现中找到这些问题的答案是使用“NM”。如果将NM输出到C++ FLT,经常被损坏的C++符号更可读。 例如,如果使用“-c”编译每个编译单元的“.o”,则可以运行nm。当我这样做时,我看到模板成员是弱符号“W”代码(在x86Linux上)。这意味着多个定义是可以的,并且以某种特定于系统的方式。如果我创建了一个非模板化的函数,它将在两个翻译单元对应的对象文件中显示为“T”。这将导致出现多个已定义的符号

通常C++模板是按需实例化的(没有完整实例化),这将允许您在声明报头之外使用一个IMPIML类型的报头。


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

在您的回答中,您提到“以某种特定于系统的方式”。这是否意味着标准中没有规定,并且可能无法携带?至于我最后一个关于函数模板的问题,我指的是更一般的函数模板,而不是类成员函数模板。谢谢。[temp.spec]p5“对于给定的模板和一组给定的模板参数,-一个显式的实例化定义在程序中最多只能出现一次[…]诊断违反此规则的行为不需要实现。”另请参阅其中包含可能未诊断的原因。@dyp,在本例中,我的程序实际上违反了14.7.0.5,但是标准说不需要g++来诊断这个问题,实际上g++解决了多重定义。但是为了使它符合标准,我应该只在一个翻译单元中定义所有实例化,并在其他翻译单元中声明(“extern”)显式模板实例化。我说得对吗?我想是的,虽然我不太明白这个要求的目的是什么a)类模板专门化b)函数模板专门化,它们要么是内联的,要么是有内部链接的。@dyp,但这让我大吃一惊。基本上,无论我写的C++代码是错误的。我应该一直添加
外部模板类std::vector
#include "test.hpp"
template class A<int>;
int testFn()
{
    return A<int>().out();
}
#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