显式 class 模板实例化的链接
Linkage of explicit class template instantiation
在不同的编译单元中是否允许具有相同类型的相同 class 模板的多个实例化?函数模板呢?
示例代码如下:
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] 的旧草案,并假设链接部分没有太大变化(匿名名称空间除外)。 class 模板具有 3.5p4 和 14p4 的外部链接。如果是这样的话,我希望 g++ 应该抱怨 A::out() 的重复定义。我在这里遗漏了什么吗?
如果 test.hpp 定义了一个没有 "static" 或 "inline" 的函数模板怎么办?
谢谢。
[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
在实现中找到这些问题的答案的一个好方法是使用 "nm." 如果将 nm 的输出通过管道传递给 c++filt,那么通常被破坏的 C++ 符号更具可读性。
例如,如果您使用“-c”编译生成“.o"s of each compilation unit, then you can run nm. When I do this I see that the template members are weak symbols "W”代码(在 x86 linux 上)。这意味着多个定义是可以的,并且以某种系统特定的方式。如果我创建一个非模板化的函数,它将在对应 object 文件的两个翻译单元中显示为 "T"。这将导致多个定义的符号。
通常 C++ 模板是根据需要实例化的(没有完全实例化),这将允许您在声明 header 之外使用 _impl 类型 header。
您实际上不允许将成员模板定义为静态的(这会出错)。您可以将其定义为内联。在这种情况下,您将看不到使用 nm 的成员模板的任何符号,因为它已被内联。
在不同的编译单元中是否允许具有相同类型的相同 class 模板的多个实例化?函数模板呢?
示例代码如下:
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] 的旧草案,并假设链接部分没有太大变化(匿名名称空间除外)。 class 模板具有 3.5p4 和 14p4 的外部链接。如果是这样的话,我希望 g++ 应该抱怨 A::out() 的重复定义。我在这里遗漏了什么吗?
如果 test.hpp 定义了一个没有 "static" 或 "inline" 的函数模板怎么办?
谢谢。
[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
在实现中找到这些问题的答案的一个好方法是使用 "nm." 如果将 nm 的输出通过管道传递给 c++filt,那么通常被破坏的 C++ 符号更具可读性。
例如,如果您使用“-c”编译生成“.o"s of each compilation unit, then you can run nm. When I do this I see that the template members are weak symbols "W”代码(在 x86 linux 上)。这意味着多个定义是可以的,并且以某种系统特定的方式。如果我创建一个非模板化的函数,它将在对应 object 文件的两个翻译单元中显示为 "T"。这将导致多个定义的符号。
通常 C++ 模板是根据需要实例化的(没有完全实例化),这将允许您在声明 header 之外使用 _impl 类型 header。
您实际上不允许将成员模板定义为静态的(这会出错)。您可以将其定义为内联。在这种情况下,您将看不到使用 nm 的成员模板的任何符号,因为它已被内联。