何时需要实例化函数模板定义?

When is required instantiation of function template definition?

本文关键字:定义 函数模板 实例化 何时需      更新时间:2023-10-16

在我读完这个问题的答案后,我仍然在问问题。答案谈到了 [temp.point] 中定义的实例化点的位置,但如果需要实例化,则不会对其进行评估。

[temp.inst] 指定何时需要函数模板专用化实例化,一般规则为:

实现不应隐式实例化函数模板、变量模板、成员

模板、非虚拟成员函数、成员类,[...],除非需要此类实例化。

此外,在标准本节的某些段落中,声明的实例化和定义的实例化是分开考虑的。

让我们考虑以下代码:

static void Yeap0(int);
template <class T>
void Yeap(T a){
Yop(a);
}
template <class T>
auto Yeap2(T a){
Yop(a);
return 0;
}
namespace x{
struct y{};
}
int main() {
Yeap0(0);//ok no definition required here
x::y ax{};
Yeap(ax); //the declaration is sufficient, 
Yeap2(ax); //need to deduce auto => definition required
//compilation error
return 0;
}
namespace x{
void Yop(y){}
}
static void Yeap0(int){}

gcc、Clang 和 MSVC 只为Yeap2(ax)产生一个错误,抱怨Yop在 Yeap2 的实例化点没有定义。

但是此错误不是为Yeap(ax)生成的。从基本考虑来看,这似乎是合乎逻辑的,只需要声明,至于 none 模板函数Yeap0

但是[temp.inst]/4的讲座让我感到困惑。可以理解,还需要实例化Yeap。但编译器似乎走了一条更聪明的道路。

编译器行为是扩展吗?


注意:我不会接受"无需诊断"的答案。这将是对智力的侮辱:人们可以相信 3 个编译器特别小心地关闭了像Yeap(ax)这样的情况的诊断,而不是Yeap2(ax)

编译器抱怨实际上来自函数返回auto的事实。

auto的情况下,你真的击中了

除非需要此类实例化。

它必须来自要求 dcl.spec.auto。

若要验证该评估,可以在代码 Yeap2 中替换为:

template <class T>
auto Yeap2(T a){
Yeap(a);
return 0;
}

并且没有编译错误。