为什么没有声明从.cpp文件中获取模板函数的完全特化?

iam*_*ind 2 c++ templates template-specialization language-lawyer

以下代码不生成编译/链接器错误/警告:

// A.h
#include<iostream>
struct A
{
  template<typename T>
  static void foo (T t)
  {
    std::cout << "A::foo(T)\n";
  }
};
void other ();

// main.cpp
#include"A.h"
int main ()
{
  A::foo(4.7);
  other();
}

// other.cpp
#include"A.h"
template<>
void A::foo (double d)
{
  cout << "A::foo(double)\n";
}

int other ()
{
  A::foo(4.7);
}
Run Code Online (Sandbox Code Playgroud)

输出令人惊讶的是:

A::foo(T)
A::foo(double)
Run Code Online (Sandbox Code Playgroud)

为什么编译器无法在正确A::foo(double)的情况下获取正确的main.cpp

同意,如果有A.h如下声明,则没有预期的问题:

template<> void A::foo (double);
Run Code Online (Sandbox Code Playgroud)

但这不是问题,因为在链接时,编译器具有专用版本.

另外,是否有2个不同版本的相同功能和未定义的行为

Ker*_* SB 6

在模板实例化时,所有显式特化声明必须是可见的.由于您的显式专业化声明A::foo<double>在一个翻译单元中可见而在另一个翻译单元中不可见,因此该程序格式错误.

(在实践中,编译器将实例在主模板main.cpp和明确的,专业性的中other.cpp,这将仍然是一个ODR违反反正.)