5

考虑下一个例子:

#include <iostream>

template< int a >
void foo();

int main(int argn, char* argv[])
{
    foo<1>();
}

template<>
void foo<1>()
{
    std::cout<<1<<std::endl;
}

编译失败并出现以下错误消息:

rg.cpp:12: error: specialization of ‘void foo() [with int a = 1]’ after instantiation

标准中的哪一段解释了这个错误?

PS:我知道如果我将函数定义移到 main 前面会使错误消失。

4

1 回答 1

10

我认为根据标准这是未定义的行为。在 UB 的情况下,工具链可以做什么没有限制,生成编译器错误是更友好的可能性之一。


[temp.spec]14.7p5 节说

对于给定的模板和给定的一组模板参数

  • 显式实例化定义在程序中最多出现一次,
  • 一个显式的特化应在程序中最多定义一次(根据 3.2),并且
  • 显式实例化和显式特化的声明都不应出现在程序中,除非显式实例化遵循显式特化的声明。

诊断违反此规则的情况不需要实现。

[temp.expl.spec]14.7.3p6 节说:

如果模板、成员模板或类模板的成员被显式特化,则应在第一次使用该特化之前声明该特化,这将导致发生隐式实例化,在发生这种使用的每个翻译单元中; 不需要诊断。


您的程序违反了这些要求。

于 2011-05-06T14:19:52.320 回答