类模板中友元函数声明的模板实参推导规则问题
考虑如下示例:
#include <iostream> template <class T, int V> struct S { friend int Func(T) // decl-1 { return V; } }; struct U { friend int Func(U); // decl-2 }; template struct S<U, 42>; // spec-1 int main() { std::cout << Func(U{}) << std::endl; // 编译通过,输出42 }
我最初的理解是:表达式Func(U{})会触发对函数Func的无限定名字查找,通过参数依赖查找(ADL)找到声明decl-2。但该声明并非重载决议的可行候选函数(因其未定义),因此编译器会选择声明decl-1。 该理解有误且与本问题无关,详见@LanguageLawyer的评论
核心问题
C++标准的哪些规则允许编译器使用特化spec-1的模板参数,来实例化包含decl-1的类模板?
查阅cppreference时,我找到的唯一可能适用的规则是关于函数模板重载决议的内容,引用如下:
对于函数模板,会执行模板实参推导与显式模板实参检查,以确定当前场景下可用的模板实参值(若存在):
- 若两项操作均成功,则使用得到的模板实参合成对应函数模板特化的声明,加入候选集;除平局决胜规则另有说明外,这类特化的处理方式与非模板函数一致;
- 若实参推导失败,或合成的函数模板特化为病式,则不会将对应函数加入候选集。
来源:cppreference 重载决议详情章节
我想确认以下问题:
- 重载决议时decl-1是否会被视为函数模板?
- 编译器是否会(推测通过模板实参推导)使用spec-1合成声明
template int Func<U, 42>(U)? - 还是该过程存在其他机制?
补充问题
我对spec-1的本质可能存在误解,目前我认为它是类模板S显式特化的不完整类型声明,也请澄清该理解是否正确。
内容的提问来源于stack exchange,提问作者Shinuzi Kyura
相关产品推荐
相关产品推荐

