使用约束重载静态和非静态成员函数
此代码有效吗?
template<bool b>
struct s {
void f() const {
}
static void f() requires b {
}
};
void g() {
s<true>().f();
}
啪的一声说是,GCC说不是
<source>: In function 'void g()':
<source>:10:20: error: call of overloaded 'f()' is ambiguous
10 | s<true>().f();
| ~~~~~~~~~~~^~
<source>:3:14: note: candidate: 'void s<b>::f() const [with bool b = true]'
3 | void f() const {
| ^
<source>:5:21: note: candidate: 'static void s<b>::f() requires b [with bool b = true]'
5 | static void f() requires b {
| ^
Compiler returned: 1
https://godbolt.org/z/f4Kb68aee
解决方案
如果我们通过[over.match.best.general],我们将获得:
一个可行函数
F1
被定义为比另一个可行函数F2
好的函数,如果对于所有参数i
,ICSi(F1)
不是比ICSi(F2)
更差的转换序列,然后[...]
唯一的参数是Object参数,我们在前面有过:
因此前提成立:一个函数的所有参数的转换序列不比另一个函数的转换序列差。所以我们进入决胜局...如果
F
是静态成员函数,则ICS1(F)
被定义为对于任何函数ICS1(F)
既不比ICS1(G)
好也不比ICS1(G)
差,并且对称地,ICS1(G)
既不比ICS1(F)
好也不比ICS1(F)
差;否则
我们可以有更好的转换序列的唯一参数是对象参数,正如所确定的那样,该参数是等价的。因此,此决胜局不适用。
- 对于某些参数
j
,ICSj(F1)
是比ICSj(F2)
更好的转换序列,如果不是这样,
- 上下文是通过用户定义的转换(参见[dcl.init]、[over.match.conv]和[over.match.ref])和[...]
进行的初始化
没有。
- 上下文是转换函数的初始化,用于直接引用绑定到函数类型的引用,[...]
没有。
F1
不是函数模板专门化,F2
是函数模板专门化,否则
没有。
F1
和F2
是函数模板专门化,根据[temp.unc.order]中描述的偏序规则,F1
的函数模板比F2
的模板专门化,如果不是这样,
没有。
F1
和F2
是具有相同参数类型列表的非模板函数,根据[temp.constr.order]中描述的约束的部分顺序,F1
比F2
更受约束,如果不是这样,
啊哈!在本例中,我们的非模板函数具有相同的参数类型列表(两者都是空的)。静态成员函数受约束,而非静态成员函数不受约束,这是受约束程度最低的一种(请参阅[temp.constr.order])。
因此,我认为Cang(和MSVC)接受这个计划是正确的,GCC拒绝它是错误的。(已提交103783)。相关文章