wal*_*nut 7 c++ function-templates template-argument-deduction
C++17 标准(最终草案)的[temp.arg.explicit]/3说明了使用明确指定的模板参数列表来推导函数模板参数:
在推导完成但失败或 [...] 的上下文中,如果指定了模板参数列表,并且它与任何默认模板参数一起标识单个函数模板特化,则模板 ID 是函数模板特化。
这如何应用于参数包?
考虑
template<typename...>
struct S {
S(int) {}
};
template<typename... A>
void f(S<A...>) {}
int main() {
f<int>(0);
}
Run Code Online (Sandbox Code Playgroud)
这在 MSVC 上编译,但不在 GCC 和 Clang 上编译,请参阅Godbolt。这也是我的直觉,它应该失败,因为演绎会失败,但上面的引用似乎暗示即使演绎失败,因为f<int>(在我的理解中)唯一标识了一个模板专业化,f<int>应该被认为是指那个专业化和然后调用它,没有重载决议,这将起作用,隐式转换0为S<int>.
我对引用的理解有什么问题,还是 MSVC 确实正确?
请注意,如果我们尝试调用f<>(0);(我猜应该通过上述考虑可以工作)所有三个编译器都拒绝编译。
这无关紧要。不存在“没有重载解析”的函数调用。CWG2092明确了这一点。
[temp.over]/1 控件(为了可读性而分开;强调我的):
当编写对函数或函数模板名称的调用(显式或隐式使用运算符表示法)时,模板参数推导 ([temp.deduct]) 和任何显式模板参数 ([temp.arg]) 的检查对每个函数模板执行以查找可与该函数模板一起使用的模板参数值(如果有)来实例化可通过调用参数调用的函数模板专业化。
对于每个函数模板,如果参数推导和检查成功,则使用模板参数(推导的和/或显式的)来合成单个函数模板特化的声明,该声明被添加到要在重载中使用的候选函数集解决。
如果对于给定的函数模板,参数推导失败或者合成的函数模板特化格式不正确,则不会将此类函数添加到该模板的候选函数集中。完整的候选函数集包括所有合成声明和所有同名的非模板重载函数。除非 [over.match.best] 中明确指出,否则在重载决策的其余部分中,合成声明的处理方式与任何其他函数类似。