C++取全默认参数函数模板地址时的模板实参推导疑问
全默认参数函数模板的实参推导规则疑问
问题描述
我希望厘清所有模板参数均设置默认值的函数模板的实参推导规则。根据C++20标准第13.10.1节(显式模板实参指定)的相关规定:当取函数地址、使用函数初始化函数引用、构造指向成员函数的指针时,若所有模板参数均可完成推导,则可全部省略模板实参,此时空模板实参列表<>本身也可省略。
但在如下代码片段的第四行中,GCC、MSVC等主流编译器均强制要求必须添加空尖括号<>才可通过编译。请问该现象是编译器不符合标准规范,还是我对规则的理解存在遗漏?
本示例中该问题影响较小,但该疑问产生自实际开发中该问题存在实质影响的场景。
template <typename T = int> void f(T) {} void (*p)(int) = f; //ok auto a = f<>; //ok auto b = f; //error, can't deduce void g() {} auto c = g; //OK
结论
你的理解存在遗漏,编译器的行为完全符合C++标准规范,核心原因如下:
- 标准中提到的可省略空模板实参列表
<>的场景,有一个必要前提:存在确定的目标类型,能够完成所有模板参数的推导。比如示例中void (*p)(int) = f;一行,等号左侧是明确的void(*)(int)类型函数指针,编译器可以直接通过目标类型推导出模板参数T=int,满足推导要求,因此可以省略<>直接写f。 - 当使用
auto声明变量时,等号左侧没有预先定义的确定目标类型,编译器需要从等号右侧的表达式推导变量类型。此时右侧的函数模板f没有任何可供推导的上下文:理论上f可以实例化为任意T对应的函数实体,即使T设置了默认值int,标准也不要求编译器在无有效推导上下文的场景下,自动套用默认模板参数完成实例化,因此auto b = f;会触发推导失败错误。 - 当你显式写出
f<>时,相当于明确告知编译器“使用所有模板参数的默认值完成实例化”,此时不需要额外的推导上下文,因此auto a = f<>;可以正常编译通过。 - 普通函数
g不存在模板实例化流程,auto c = g;可以直接取函数地址推导对应的函数指针类型,因此可以正常编译。
内容的提问来源于stack exchange,提问作者user1958486
相关产品推荐
相关产品推荐

