У вас неопределенное поведение из-за проблем ODR.
ODR говорит, что для каждого символа должно быть только одно определение.Встроенные и шаблонные функции могут иметь несколько определений, но должны иметь одинаковую реализацию, токен за токеном.Диагностика не требуется, если это правило нарушено.
При компиляции вашего примера компилятор создаст экземпляр вашей функции.Посмотрите на это:
template <int>
void func() { std::cerr << "default impl\n"; } // normally no impl here
int main(void)
{
func<1>();
func<2>();
return 0;
}
Это то, что видит компилятор.Он не может видеть другие файлы cpp.Компилятор создаст экземпляры шаблонов и создаст дополнительное определение для ваших функций.
Тогда ваш другой файл cpp предоставит другое определение, отличное.
Решением этого является прямое объявление специализаций вВаш заголовок:
template<> void func<1>();
template<> void func<2>();
Это сообщит компилятору, что специализации объявлены в другом месте, а не создает экземпляр по умолчанию.