在取地址的上下文中,哪个是最专业的函数模板?



考虑以下示例

#include <iostream>
template<class T>
void fun(T&){  //#1
std::cout<<"selectedn";
}
template<class T>
void fun(T&&){}  //#2
int main() {
void(*ptr)(int&) = &fun;  //#3
}

GCC和Clang都报告了诊断"含糊不清"的错误。根据[temp. deduction .funcaddr#1],这两个函数模板在#3中都是可行的。因此,[结束。> #5]需要在这里应用

如果该集合包含第二个函数模板专门化,且该函数模板根据[temp. function .order]的偏序规则比F1的函数模板专门化程度更高,则消除给定的函数模板专门化F1。

为了判断#1#2哪个更专门化,[temp. deduction .partial#3.3]适用于它们

用于确定排序的类型取决于进行部分排序的上下文:

  • […]
  • 其他上下文中,函数模板的函数类型使用。
因此,p和A用于参与偏排序应该分别是这两个函数模板的函数类型。设#2的函数类型为P,#1的函数类型为a。根据[temp. deduction .type#10],从A推导出P成功。

如果p和函数类型,起源于扣除当把一个函数模板的地址([temp.deduct.funcaddr])或当推断模板参数的函数声明([temp.deduct.decl])和π和Ai的顶级parameter-type-list参数p和,分别调整Pi如果是转发参考([temp.deduct.call])和人工智能是一个左值引用,在这种情况下,π的类型是改变模板参数类型(例如,T&和;

相反,由于我们不能从T&&推导出T&,因此#1的函数模板比#2的函数模板更专门化。因此,#2的专门化应该从集合中消除。最终,该集合只包含#1的一个专门化。这里应该是明确的。为什么GCC和Clang说接收地址是模糊的?

GCC和Clang在重载解析中产生歧义是错误的,根据您自己的分析。

这可能与CWG 1164有关,尽管不是在函数调用的上下文中,但其意图应该与CWG 1164中函数调用的情况相似[强调]我:

1164。f(T&)和f(T&&)的偏序

章节:13.10.3.2 [temp. deduction .call]状态:c++ 11提交者:US日期:2010-08-03

[在2010年11月的会议上投票加入WP]

N3092注释US 77下面的例子有歧义:

template<typename T> int f(T&);
template<typename T> int f(T&&);
int i;
int j = f(i);

由于传递给的左值的特殊扣除规则右值引用形参,演绎对两者都产生f(int&)模板,它们是无法区分的。

因为f(T&)接受f(T&&)所做的事情的严格子集,它应该被认为是更专门化的部分排序规则。

建议决议(August, 2010):[…]

您自己的分析达到了与CWG 1164一致的过载结果,但用于另一个上下文中,这在CWG 1164中从未解除,并且(可以说)不太常见。


我们可能会注意到GCC和Clangs都将CWG 1164的解决方案标记为?/Unknown:
- GCC: GCC
- Clang
支持c++缺陷报告所以可能它只是部分实现(OP的例子比CWG 1164更像是一个角落用例)。

最新更新