Специализация функции шаблона после точки использования нарушит компиляцию

Рассмотрим следующий пример:

#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: Я знаю, что если я переведу определение функции перед основной, произойдет ошибка.

Ответ 1

Я думаю, что поведение undefined в соответствии со стандартом. Нет никаких ограничений на то, что может сделать toolchain в случаях UB, генерация ошибки компилятора является одной из более дружественных возможностей.


Раздел [temp.spec], 14.7p5 говорит

Для данного шаблона и заданного набора шаблонов-аргументов

  • явное определение инстанцирования должно появляться не более одного раза в программе,
  • явная специализация должна определяться не более одного раза в программе (согласно 3.2), а
  • как явное инстанцирование, так и объявление явной специализации не должны появляться в если явное инстанцирование не следует декларации явной специализации.

Реализация не требуется для диагностики нарушения этого правила.

Раздел [temp.expl.spec] 14.7.3p6 говорит:

Если шаблон, шаблон-член или член шаблона класса явно специализирован, то , что специализация должна быть объявлена ​​до первого использования этой специализации, которая вызовет неявное создание экземпляра, в каждой единицы перевода, в которой такое использование происходит; диагностика не требуется.


Ваша программа нарушает эти требования.