在获取地址的上下文中,哪个是最专业的函数模板?
Which is the most specialized function template in the context of taking the address?
考虑这个example
#include <iostream>
template<class T>
void fun(T&){ //#1
std::cout<<"selected\n";
}
template<class T>
void fun(T&&){} //#2
int main() {
void(*ptr)(int&) = &fun; //#3
}
GCC 和 Clang 都报告错误,诊断为“不明确”。根据[temp.deduct.funcaddr#1],这两个函数模板在#3
中都是可行的。因此,[over.over#5]需要在这里申请
Any given function template specialization F1 is eliminated if the set contains a second function template specialization whose function template is more specialized than the function template of F1 according to the partial ordering rules of [temp.func.order].
判断#1
和#2
哪个更专业,[temp.deduct.partial#3.3]适用于
The types used to determine the ordering depend on the context in which the partial ordering is done:
- [...]
- In other contexts the function template's function type is used.
因此,参与偏序的P和A应该分别是那两个函数模板的函数类型。取#2
函数类型为P,#1
函数类型为A,A
推P
成功[temp.deduct.type#10]
If P and A are function types that originated from deduction when taking the address of a function template ([temp.deduct.funcaddr]) or when deducing template arguments from a function declaration ([temp.deduct.decl]) and Pi and Ai are parameters of the top-level parameter-type-list of P and A, respectively, Pi is adjusted if it is a forwarding reference ([temp.deduct.call]) and Ai is an lvalue reference, in which case the type of Pi is changed to be the template parameter type (i.e., T&& is changed to simply T).
相反,由于我们无法从 T&&
推导出 T&
,因此 #1
处的函数模板比 #2
处的函数模板更专业。因此,#2
的特化应该从集合中删除。最终,该集合仅包含 #1
的一个特化。这里应该是不含糊的。为什么GCC和Clang都说取地址不明确?
根据您自己的分析,GCC 和 Clang 在重载决策中的屈服和歧义是错误的。
这可以说与 CWG 1164, albeit not being in the context of a function call 有关,其意图可以说与 CWG 1164 [强调 我的函数调用的情况相似]:
1164. Partial ordering of f(T&) and f(T&&)
Section: 13.10.3.2 [temp.deduct.call] Status: C++11 Submitter: US Date: 2010-08-03
[Voted into the WP at the November, 2010 meeting.]
N3092 comment US 77 The following example is ambiguous:
template<typename T> int f(T&);
template<typename T> int f(T&&);
int i;
int j = f(i);
Because of the special deduction rule for lvalues passed to
rvalue-reference parameters, deduction produces f(int&) for both
templates, and they are indistinguishable.
Because f(T&) accepts a strict subset of the things that f(T&&) does,
it should be considered more specialized by the partial ordering
rules.
Proposed resolution (August, 2010): [...]
您自己的分析得出了一个与 CWG 1164 一致的过载结果,但对于另一个上下文,它从未在 CWG 1164 中解除并且(可以说)不太常见。
我们可能会注意到 GCC 和 Clangs 都将 CWG 1164 的决议标记为 ?
/Unknown
:
- GCC: C++ Defect Report Support in GCC
- C++ Defect Report Support in Clang
所以它可能只是部分实施(OP 的示例比 CWG 1164 的示例更多的是角落用例)。
考虑这个example
#include <iostream>
template<class T>
void fun(T&){ //#1
std::cout<<"selected\n";
}
template<class T>
void fun(T&&){} //#2
int main() {
void(*ptr)(int&) = &fun; //#3
}
GCC 和 Clang 都报告错误,诊断为“不明确”。根据[temp.deduct.funcaddr#1],这两个函数模板在#3
中都是可行的。因此,[over.over#5]需要在这里申请
Any given function template specialization F1 is eliminated if the set contains a second function template specialization whose function template is more specialized than the function template of F1 according to the partial ordering rules of [temp.func.order].
判断#1
和#2
哪个更专业,[temp.deduct.partial#3.3]适用于
The types used to determine the ordering depend on the context in which the partial ordering is done:
- [...]
- In other contexts the function template's function type is used.
因此,参与偏序的P和A应该分别是那两个函数模板的函数类型。取#2
函数类型为P,#1
函数类型为A,A
推P
成功[temp.deduct.type#10]
If P and A are function types that originated from deduction when taking the address of a function template ([temp.deduct.funcaddr]) or when deducing template arguments from a function declaration ([temp.deduct.decl]) and Pi and Ai are parameters of the top-level parameter-type-list of P and A, respectively, Pi is adjusted if it is a forwarding reference ([temp.deduct.call]) and Ai is an lvalue reference, in which case the type of Pi is changed to be the template parameter type (i.e., T&& is changed to simply T).
相反,由于我们无法从 T&&
推导出 T&
,因此 #1
处的函数模板比 #2
处的函数模板更专业。因此,#2
的特化应该从集合中删除。最终,该集合仅包含 #1
的一个特化。这里应该是不含糊的。为什么GCC和Clang都说取地址不明确?
根据您自己的分析,GCC 和 Clang 在重载决策中的屈服和歧义是错误的。
这可以说与 CWG 1164, albeit not being in the context of a function call 有关,其意图可以说与 CWG 1164 [强调 我的函数调用的情况相似]:
1164. Partial ordering of f(T&) and f(T&&)
Section: 13.10.3.2 [temp.deduct.call] Status: C++11 Submitter: US Date: 2010-08-03
[Voted into the WP at the November, 2010 meeting.]
N3092 comment US 77 The following example is ambiguous:
template<typename T> int f(T&); template<typename T> int f(T&&); int i; int j = f(i);
Because of the special deduction rule for lvalues passed to rvalue-reference parameters, deduction produces f(int&) for both templates, and they are indistinguishable.
Because f(T&) accepts a strict subset of the things that f(T&&) does, it should be considered more specialized by the partial ordering rules.
Proposed resolution (August, 2010): [...]
您自己的分析得出了一个与 CWG 1164 一致的过载结果,但对于另一个上下文,它从未在 CWG 1164 中解除并且(可以说)不太常见。
我们可能会注意到 GCC 和 Clangs 都将 CWG 1164 的决议标记为 ?
/Unknown
:
- GCC: C++ Defect Report Support in GCC
- C++ Defect Report Support in Clang
所以它可能只是部分实施(OP 的示例比 CWG 1164 的示例更多的是角落用例)。