显式模板实例化如何影响链接器可以找到的内容?

Sur*_*uri 10 c++ templates

请参阅以下代码,请清除我的疑虑.

  1. 由于ABC是一个模板,为什么当我们在test.cpp中放置ABC类成员函数的定义时它不显示错误?

  2. 如果我在test.h和remve 2中放入test.cpp代码,那么它可以正常工作.为什么?

.

// test.h 
template <typename T> 
class ABC { 
public: 
   void foo( T& ); 
   void bar( T& ); 
}; 
// test.cpp 
template <typename T> 
void ABC<T>::foo( T& ) {} // definition 
template <typename T> 
void ABC<T>::bar( T& ) {} // definition 

template void ABC<char>::foo( char & );  // 1 
template class ABC<char>;                // 2 
// main.cpp 
#include "test.h" 
int main() { 
   ABC<char> a; 
   a.foo();     // valid with 1 or 2 
   a.bar();     // link error if only 1, valid with 2 
} 
Run Code Online (Sandbox Code Playgroud)

Dav*_*eas 13

在这两种情况下,您都在进行显式实例化.在第二种情况下,仅ABC<char>::foo实例化,而在第一种情况下ABC<char>::bar也被实例化.

一个不同的类似例子可以澄清其含义:

// test.h
template <typename T>
class ABC {
public:
   void foo( T& );
   void bar( T& );
};
// test.cpp
template <typename T>
void ABC<T>::foo( T& ) {} // definition
template <typename T>
void ABC<T>::bar( T& ) {} // definition

template void ABC<char>::foo( char & );  // 1
template class ABC<char>;                // 2
// main.cpp
#include "test.h"
int main() {
   ABC<char> a;
   a.foo();     // valid with 1 or 2
   a.bar();     // link error if only 1, valid with 2
}
Run Code Online (Sandbox Code Playgroud)

在示例中,在main编译器中看不到foo也没有bar定义,因此无法实例化方法.处理main.cpp时,编译器会很乐意接受main中的代码,因为你告诉它ABC是一个模板并且它有这两个函数,并假设它们将在其他一些翻译单元中定义.

在包含test.cpp的转换单元中,编译器会看到两个方法定义,并且可以完全处理这两个实例(方法/类).如果仅存在方法实例化([1]),则编译器将仅生成该方法,并将保留bar未定义.因此,任何包含test.h的代码,针对已编译的test.cpp的链接以及仅使用foo方法都将进行编译和链接,但bar由于未定义,因此无法使用链接.

显式实例化类模板会为所有成员方法生成符号,在这种情况下,任何包含test.h的翻译单元和编译的test.cpp对象文件的链接都将编译和链接.