具有自动功能的模板函数的重载分辨率

overload resolution of template function with auto

本文关键字:函数 重载 分辨率 功能      更新时间:2023-10-16

以下 3 个重载

template <class T> auto foo() { return 1; }
template <class T> int  foo() { return 2; }
template <class T> T    foo() { return 3; }

以下是否形成不良?

static_cast<int(*)()>(&foo<int>)();

Clang选择重载#2,而gcc无法编译(演示)

删除重载 #1 时,双方都同意选择重载 #2(演示)。

删除重载 #2 时,gcc 选择重载 #1 并且 clang 无法编译(演示)

根据 [over.over]/2,我们执行模板参数推导。这将对所有三个重载成功:在第一个重载中,记住 [temp.deduct.funcaddr]/2:

函数模板的返回类型中的占位符类型 (7.1.7.4) 是非推导上下文。如果模板 参数推导成功 对于这样的函数,返回类型由 函数体。

由于推导将成功(假设所有模板参数都显式提供了参数),因此返回类型推导为int。在第二种情况下,由于提供了参数,因此演绎成功,在第三种情况下,将推导出T

继续讨论第4段,

如果选择了多个函数,[...] 函数模板专用化F1如果集合包含 第二个函数模板专用化,其函数模板为 比F1的函数模板更专业 14.5.6.2 的部分排序规则。在此种冲销之后,如有的话,应只剩下一个选定的职能。

根据 [temp.deduct.partial]/3,函数模板的函数类型用于部分排序。我们可以立即看到 #1 和 #2 的函数类型不包含任何参与演绎的模板参数,因此通过核心问题 1391 的决议引入的 [temp.deduct.partial]/4 的添加,它们的相应Ps 不用于确定排序。@bogdan在这里解释了为什么该决议有问题;底线是排序只会产生 #1 和 #2 的歧义。

也就是说,根据当前(可能有缺陷)的措辞,转换在所有情况下都是格式不正确的。如果非因/推导参数对的部分排序是固定的,

情况 1 和
  • 3 不明确,因为对于两个非依赖函数类型(#1 和 #2 的函数类型),没有排序对。
  • 案例 2 中的接受行为是正确的(如预期的那样)。

[temp.deduct.type]/8 element 9 (T()),以防您好奇。