为什么这个C++显式模板特化代码是非法的?

BCS*_*BCS 7 c++ templates language-specifications explicit-specialization

(注意:我知道这是非法的,我正在寻找这种语言的原因.)

template<class c> void Foo();  // Note: no generic version, here or anywhere.

int main(){
  Foo<int>();
  return 0;
}

template<> void Foo<int>();
Run Code Online (Sandbox Code Playgroud)

错误:

error: explicit specialization of 'Foo<int>' after instantiation
Run Code Online (Sandbox Code Playgroud)

谷歌的快速传递发现了这个规范的引用,但这只提供了什么,而不是原因.

编辑:

一些回复转发了这一论点(例如证实了我的推测),即规则是这样的,因为否则会违反一个定义规则(ODR).然而,这是一个非常弱的论点,因为在这种情况下,它不适用于两个原因:

  1. 将显式特化移动到另一个翻译单元可以解决问题,并且似乎没有违反ODR(或链接器说的那样).
  2. ODR的缩写形式(适用于函数)是指任何给定函数都不能有多个正文,而我不能.函数体的唯一定义位置是显式特化,因此调用Foo<int>不能定义模板的泛型特化,因为没有专用的泛型体.

关于此事的猜测:

关于为什么规则存在的猜测:如果第一行提供了一个定义(而不是一个声明),实例化后的显式特化将是一个问题,因为你会得到多个定义.但在这种情况下,唯一的定义是明确的专业化.

奇怪的是,以下(或者我正在处理的实际代码中的类似内容)有效:

文件A:

template<class c> void Foo();

int main(){
  Foo<int>();
  return 0;
}
Run Code Online (Sandbox Code Playgroud)

档案B:

template<class c> void Foo();

template<> void Foo<int>();
Run Code Online (Sandbox Code Playgroud)

但总的来说,使用它开始创造一个意大利面条进口结构.

ral*_*nja 5

关于为什么规则存在的猜测:如果第一行提供了一个定义(而不是一个声明),实例化后的显式特化将是一个问题,因为你会得到多个定义.但在这种情况下,唯一的定义是明确的专业化.

但是你确实有多个定义.在实例化它时,您已经定义了Foo <int>,之后您尝试专门化已经定义的int的模板函数.

int main(){
  Foo<int>();    // Define Foo<int>();
  return 0;
}

template<> void Foo<int>(); // Trying to specialize already defined Foo<int>
Run Code Online (Sandbox Code Playgroud)

  • 虽然这可能在技术上是正确的,但它并不是我的问题. - 如何`Foo <inT>()`定义什么?编译器不知道函数的主体是什么,所以它能做的最好的事情是找出函数的(受损)名称是什么,并注入链接器将修补的调用.此外,如果这确实在这里定义了'Foo <in>,那么即使将显式特化移动到另一个文件中也不应该解决问题,因为你仍然会违反一个定义规则. (3认同)