为什么显式模板实例化的位置很重要

Dej*_*vić 5 c++ templates explicit

说我声明一个模板类Aa.h

#include <iostream>

template<bool b>
class A { 
public:
  void print(std::ostream& out);
};
Run Code Online (Sandbox Code Playgroud)

并确定在打印方法a.cpp(与明确的instatiation truefalse)

#include "a.h"

template<bool b>
void A<b>::print(std::ostream& out) {
  out << "A" << b;
}

template class A<true>;
template class A<false>;
Run Code Online (Sandbox Code Playgroud)

main.cpp可以是一个主要的主要程序示例

#include "a.h"

int main() {
  A<true> a;
  a.print(std::cout);
}
Run Code Online (Sandbox Code Playgroud)

上面的小项目编译得很好.

问题:如果我将显式实例化放在print方法(in a.cpp)的定义之上,则代码不再编译,并且通常会undefined reference to A<true>::print(...)出现错误.

#include "a.h"

template class A<true>;
template class A<false>;

template<bool b>
void A<b>::print(std::ostream& out) {
  out << "A" << b;
}
Run Code Online (Sandbox Code Playgroud)

为什么会这样?

编辑:Makefile进行编译

main : main.o a.o
    g++ main.o a.o -o main

main.o : main.cpp
    g++ -c main.cpp

a.o : a.cpp 
    g++ -c a.cpp
Run Code Online (Sandbox Code Playgroud)

jog*_*pan 8

我认为没有一个很好的自然解释为什么会这样.显然,编译器可以看到成员函数的定义,即使它是在显式实例化之后提供的 - 因为它位于同一个文件中.

但是,编译器不需要这样做; 事实上,标准明确禁止:

(§14.7.2/ 9)命名类模板特化的显式实例化定义显式实例化类模板特化,并且是仅在实例化时定义的那些成员的显式实例化定义.

我猜其原因包括:

  • 对于稍后在翻译单元中的某些成员函数,可能存在若干不同的显式特化; 同样符合程序员的利益,有一个关于哪些将被实例化的明确规则是有道理的;

  • 隐式实例化模板时,仅考虑在实例化之前定义的特化; 所以隐式和显式实例化的规则是相同的.