【发布时间】:2015-08-11 21:47:27
【问题描述】:
是否允许在不同的编译单元中使用相同类型的同一类模板的多个实例化?函数模板呢?
示例代码如下:
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();
}
test2.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
【问题讨论】:
-
[temp.spec]p5 "对于一个给定的模板和一组给定的模板参数,一个明确的实例化定义在一个程序中最多出现一次 [...]诊断违反此规则的情况不需要实施。”
-
另见CWG NAD 1045,其中包含可能未诊断出来的原因。
-
@dyp,在这种情况下,我的程序实际上违反了 14.7.0.5,但标准说 g++ 不需要诊断这一点,实际上 g++ 解决了多重定义。但是为了使其符合标准,我应该只在一个翻译单元中定义所有实例化,并在其他翻译单元中声明(“extern”)显式模板实例化。我说的对吗?
-
我猜是这样,虽然我不太明白这个要求的目的 a) 类模板特化 b) 函数模板特化是
inline或具有内部链接。 -
@dyp,这让我大吃一惊。基本上我写的任何 C++ 代码都是错误的。我应该一直添加
extern template class std::vector<int>。
标签: c++ templates c++11 linkage