c++ - 使用外部模板时出现链接器错误

标签 c++ templates linker c++11

我有带模板的工作代码。与 STL::string 类似,我主要在多个编译单元中使用带有一个参数的模板。为了节省时间,我尝试使用外部实例化。但是,如下更改行会产生错误。正确的做法是什么? (附:使用 c++0x 标志在 gcc 上编译)

typedef myTemplate_base<commonType> myTemplate;
extern template class myTemplate_base<commonType>; //using "extern template myTemplate" wont work

我在项目中添加了一个包含以下内容的额外 cpp 文件。

template class myTemplate_base<commonType>;

链接器给出了这个错误消息(将主文件中第一个对象实例化 ( myTemplate someVar; ) 的行作为错误源):

undefined reference 'myTemplate_base::~myTemplate_base()'

但是这个类型在具有以下定义的类中 ~myTemplate() = default;

编辑:如果您有更好的标题请发表评论,以便合适的人看一看

Edit2:有趣的是,添加了template class myTemplate_base<commonType>。极大地增加了可执行文件的大小(在 450k 的二进制文件上增加了 100k),即使在主文件中使用了模板(为了编译我必须注释掉 extern 部分)。这暗示链接器保留了具有相同实例化的模板的两个实现/我忽略了某些东西。

最佳答案

您发现了一个编译器错误。我用 g++ (Ubuntu/Linaro 4.6.1-9ubuntu3) 4.6.1 复制了它。解决方法是将析构函数保留为隐式默认值。仅当析构函数被显式标记为默认 (= default) 时才会出现链接器错误。

无论哪种方式,析构函数都不会使用 extern 模板生成。将模板类标记为 extern,编译器会注意到任何需要的符号都是 extern。除了析构函数,它仍然在文件中定义。看起来用 extern 模板添加 = default 会使编译器混淆,认为析构函数将在别处定义。

代码膨胀是由外部模板引起的。编译器只实例化实际使用的模板类的方法。这通常比定义的数量少得多。当您用 extern template 强制实例化一个类时,编译器会为所有方法发出代码(除了您刚刚发现的析构函数)。


g++ -c -std=c++0x main.cpp
g++ -c -std=c++0x extern.cpp
g++ main.o extern.o

标题.hpp

#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>;

外部.cpp

#include "header.hpp"

template class Foo<int>;

main.cpp

#include "header.hpp"

int main()
{
   Foo<int> fi;
   fi.printer();

   Foo<float> ff;
   ff.printer();
}

关于c++ - 使用外部模板时出现链接器错误,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/8560839/

相关文章:

iphone - 弱链接 iPhone 应用程序的多个框架 (-weak_framework)

c++ - 使用 boost 进程编译一个简单的应用程序会生成错误

c++ - super 计算机上的 OpenMP

c++ - 铛。嵌套模板的二元运算符重载

c++ - 模板类成员函数的模板特化

python - Cython:反教程行为

c++ - 尽管包含 header ,但g++链接器无法找到函数

c++ - 当指定 O2 标志时,gcc 链接到错误的 GLIBCXX 版本

c++ - 如何在 qt main() 中运行 post 请求

c++ - 数组索引越界分配问题