ted*_*ted 5 c++ linker templates c++11
我有一个模板工作代码.与stl :: string类似,我主要使用我的模板,在多个编译单元中有一个参数.为了节省时间,我试图使用extern实例化.但是,如下更改行会产生错误.做正确的方法是什么?(PS使用c ++ 0x标志编译gcc)
typedef myTemplate_base<commonType> myTemplate;
extern template class myTemplate_base<commonType>; //using "extern template myTemplate" wont work
Run Code Online (Sandbox Code Playgroud)
我在项目中添加了一个带有以下内容的额外cpp文件.
template class myTemplate_base<commonType>;
Run Code Online (Sandbox Code Playgroud)
链接器出现此错误消息(myTemplate someVar;将主文件中的第一个对象instantiation()行作为错误源):
未定义的引用'myTemplate_base :: ~myTemplate_base()'
但是,此类型在类中具有以下定义 ~myTemplate() = default;
编辑:如果你有一个更好的标题请评论,所以合适的人看看这个
编辑2:有趣的是,添加template class myTemplate_base<commonType>会极大地增加可执行文件的大小(在450k二进制文件上+ 100k),即使模板在main中使用(编译我必须注释掉extern部分).这暗示链接器保持模板的两个实现具有相同的实例/我忽略了某些东西.
您找到了编译器错误.我转载它g++ (Ubuntu/Linaro 4.6.1-9ubuntu3) 4.6.1.解决方法是将析构函数保留为隐式默认值.仅当析构函数显式标记为default(= default)时才会出现链接器错误.
无论哪种方式,析构函数永远不会使用extern模板生成.将模板类标记为extern,编译器会注意到任何需要的符号都是extern.除了析构函数之外,它仍然在文件中定义.看起来添加一个= defaultextern模板会让编译器误认为析构函数将在别处定义.
代码膨胀是由extern模板引起的.编译器仅实例化实际使用的模板类的方法.这通常远远小于定义的数量.当您使用force实例化一个类时extern template,编译器会为所有方法发出代码(您刚刚发现的析构函数除外).
g++ -c -std=c++0x main.cpp
g++ -c -std=c++0x extern.cpp
g++ main.o extern.o
Run Code Online (Sandbox Code Playgroud)
#pragma once
#include <iostream>
#include <string>
#include <typeinfo>
template< typename T >
class Foo
{
public:
Foo( void ) :
m_name( typeid(T).name() ),
m_t( T() )
{ }
// add or remove this to cause the error
~Foo( void ) = default;
void printer( void )
{
std::cout << m_name << std::endl;
}
T returner( void )
{
return m_t;;
}
private:
std::string m_name;
T m_t;
};
extern template class Foo<int>;
Run Code Online (Sandbox Code Playgroud)
#include "header.hpp"
template class Foo<int>;
Run Code Online (Sandbox Code Playgroud)
#include "header.hpp"
int main()
{
Foo<int> fi;
fi.printer();
Foo<float> ff;
ff.printer();
}
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
1534 次 |
| 最近记录: |