根据我是使用-O3编译还是未经优化而编译,编译器不会选择相同的function-template-instanciation。使用gcc(Debian 8.3.0-6)8.3.0。
由于疏忽,我在函数模板声明中有一个默认实现:
#pragma once
#include <iostream>
template <int>
void func() { std::cerr << "default impl\n"; } // normally no impl here
及其专业:
#include "func.h"
template <>
void func<1>()
{
std::cerr << "special 1\n";
}
template <>
void func<2>()
{
std::cerr << "special 2\n";
}
和主要功能。
#include "func.h"
int main(void)
{
func<1>();
func<2>();
return 0;
}
编译并运行可以g++ -Wall func.cpp main.cpp -o main && ./main
得到:
special 1
special 2
使用优化可以g++ -O3 -Wall func.cpp main.cpp -o main && ./main
得出:
default impl
default impl
这是预期的吗?代码是否触发了我不知道的意外行为?
感谢@NathanOliver提出了Wandbox的评论。进行优化或不进行优化都会显示不同的输出。
您的代码格式错误,无需诊断。因此,不同优化级别的不同行为是可能的。
[temp.expl.spec]
6如果一个模板,一个成员模板或一个类模板的成员被明确地专门化,则应在首次使用该专门化之前声明该专门化,这将在每个使用该翻译的翻译单元中引起隐式实例化发生 无需诊断。如果程序没有为显式专门化提供定义,并且以某种方式使用专门化会导致隐式实例化,或者该成员是虚拟成员函数,则该程序格式错误,无需诊断。对于已声明但未定义的显式专门化,永远不会生成隐式实例化。
功能模板专用于一个TU,但是另一个没有可用的专用声明。积极的优化器很可能会选择隐式实例化(可在线使用),而不是在其他地方找到您创建的实例化实例。解决方案是声明标头中存在您的专业化知识。