函数模板实例化、替换和重载解析的顺序是什么?


#include <iostream>
template<typename T>
void test(T,typename T::type){  //#1
}
template<typename T,typename U>
void test(T,U){  //#2
}
int main(){
test(0,0); //we know #2 is called
}

考虑上面的代码,要调用函数test的参数0,0,编译器需要为这些参数找到最佳匹配重载并实例化函数模板,首先有两个名为test的函数模板,编译器从它们的参数中推导出模板参数。我想知道下一步中首先在函数模板上执行的实例化或替换?重载解析是否在它们之后执行?

何时实例化函数模板

如果调用重载函数模板的名称,编译器将尝试推断其模板参数并检查其显式声明的模板参数。如果成功,它将实例化函数模板专用化,然后将此专用化添加到重载解析中使用的候选函数集中

何时执行替换

具体而言,在为重载解析创建候选集时,该集的某些(或全部(候选集可能是实例化模板的结果,其中(可能推导的(模板参数替换为相应的模板参数。如果在替换任何给定模板的一组参数期间发生错误,编译器将从候选集中删除潜在的重载,而不是因编译错误而停止,前提是替换错误是C++标准允许这种处理的错误之一

我没有找到有关替换和实例化顺序的文档

更新:
deductionsubstitution(sfinae 发生在这里(是实例化的一部分,但是,除了这些之外,通过在实例化点替换模板参数来生成定义也是实例化的一部分,什么时候发生?在重载解决之后或substitution之后(这里是 sfinae(?

您的示例对您的问题没有太多说明,因为只有一个可行的候选者:替换#1失败,因为int::type格式不正确,因此只有一个函数,#2

另一方面,它确实意味着参数替换必须作为实例化的一部分发生(如@IgorTandetnik所述(。而且,要解决任何重载问题,必须在之前进行模板实例化。

如果将#1更改为

template <typename T>
void test(T,T){}

您将有两个可行的重载,并且#1将被选中。

编辑:

另一方面,如果您将主要功能更改为

struct {
using type = int;
int val = 0;
} x;
test(x,0);

两个模板都将实例化,但重载解析将失败,因为两个函数void test(anonymous struct, int)不明确。

这也说明了必须先实例化模板,然后才能进行重载解析。

最新更新