使用约束重载静态和非静态成员函数
Overloading static and non-static member function with constraint
此代码有效吗?
template<bool b>
struct s {
void f() const {
}
static void f() requires b {
}
};
void g() {
s<true>().f();
}
clang 说是,但 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
如果我们遍历 [over.match.best.general],我们得到:
a viable function F<sub>1</sub>
is defined to be a better function than another viable function F<sub>2</sub>
if for all arguments i
, ICS<sub>i</sub>(F<sub>1</sub>)
is not a worse conversion sequence than ICS<sub>i</sub>(F<sub>2</sub>)
, and then [...]
唯一的参数是对象参数,我们之前有:
If F
is a static member function, ICS<sub>1</sub>(F)
is defined such that ICS<sub>1</sub>(F)
is neither better nor worse than ICS<sub>1</sub>(G)
for any function G
, and, symmetrically, ICS<sub>1</sub>(G)
is neither better nor worse than ICS<sub>1</sub>(F)
; otherwise,
所以前提成立:一个函数的所有参数的转换序列都不会比另一个函数的转换序列差。所以我们继续决胜局...
- for some argument
j
, ICS<sub>j</sub>(F<sub>1</sub>)
is a better conversion sequence than ICS<sub>j</sub>(F<sub>2</sub>)
, or, if not that,
我们可以为其提供更好转换序列的唯一参数是对象参数,并且正如所确定的那样,该参数是等价的。所以这个决胜局不适用。
- the context is an initialization by user-defined conversion (see [dcl.init], [over.match.conv], and [over.match.ref]) and [...]
没有。
- the context is an initialization by conversion function for direct reference binding of a reference to function type, [...]
没有。
F1
is not a function template specialization and F2
is a function template specialization, or, if not that,
没有。
F1
and F2
are function template specializations, and the function template for F1
is more specialized than the template for F2
according to the partial ordering rules described in [temp.func.order], or, if not that,
没有。
F1
and F2
are non-template functions with the same parameter-type-lists, and F1
is more constrained than F2
according to the partial ordering of constraints described in [temp.constr.order], or if not that,
啊哈!在这个例子中,我们有具有相同参数类型列表的非模板函数(两者都是空的)。静态成员函数有约束,非静态成员函数没有约束,是最琐碎的一种“多约束”(参见[temp.constr.order])。
因此,我认为 clang(和 msvc)接受程序是正确的,gcc 拒绝它是错误的。 (已提交 103783)。
根据 C++20 标准,您的代码格式错误class.static.mfct#2:
There shall not be a static and a non-static member function with the same name and the same parameter types ([over.load]).
这里也不例外,也有requires
子句来区分成员函数,只是名称相同,参数类型相同。而这正是我们的情况:相同的名称是f
,相同的参数类型是空集。
所以Clang和MSVC在接受代码时是错误的。但是 GCC 的诊断肯定是混乱的。
通过对代码进行一些小的调整(删除非静态成员函数中的 const
并在代码中获取其地址),Clang 和 MSVC 也显示出大问题:
template<bool b>
struct s {
void f() {}
static void f() requires b {}
};
int main() {
s<true>().f();
void (s<true>::*x)() = &s<true>::f;
}
此代码有效吗?
template<bool b>
struct s {
void f() const {
}
static void f() requires b {
}
};
void g() {
s<true>().f();
}
clang 说是,但 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
如果我们遍历 [over.match.best.general],我们得到:
a viable function
F<sub>1</sub>
is defined to be a better function than another viable functionF<sub>2</sub>
if for all argumentsi
,ICS<sub>i</sub>(F<sub>1</sub>)
is not a worse conversion sequence thanICS<sub>i</sub>(F<sub>2</sub>)
, and then [...]
唯一的参数是对象参数,我们之前有:
If
F
is a static member function,ICS<sub>1</sub>(F)
is defined such thatICS<sub>1</sub>(F)
is neither better nor worse thanICS<sub>1</sub>(G)
for any functionG
, and, symmetrically,ICS<sub>1</sub>(G)
is neither better nor worse thanICS<sub>1</sub>(F)
; otherwise,
所以前提成立:一个函数的所有参数的转换序列都不会比另一个函数的转换序列差。所以我们继续决胜局...
- for some argument
j
,ICS<sub>j</sub>(F<sub>1</sub>)
is a better conversion sequence thanICS<sub>j</sub>(F<sub>2</sub>)
, or, if not that,
我们可以为其提供更好转换序列的唯一参数是对象参数,并且正如所确定的那样,该参数是等价的。所以这个决胜局不适用。
- the context is an initialization by user-defined conversion (see [dcl.init], [over.match.conv], and [over.match.ref]) and [...]
没有。
- the context is an initialization by conversion function for direct reference binding of a reference to function type, [...]
没有。
F1
is not a function template specialization andF2
is a function template specialization, or, if not that,
没有。
F1
andF2
are function template specializations, and the function template forF1
is more specialized than the template forF2
according to the partial ordering rules described in [temp.func.order], or, if not that,
没有。
F1
andF2
are non-template functions with the same parameter-type-lists, andF1
is more constrained thanF2
according to the partial ordering of constraints described in [temp.constr.order], or if not that,
啊哈!在这个例子中,我们有具有相同参数类型列表的非模板函数(两者都是空的)。静态成员函数有约束,非静态成员函数没有约束,是最琐碎的一种“多约束”(参见[temp.constr.order])。
因此,我认为 clang(和 msvc)接受程序是正确的,gcc 拒绝它是错误的。 (已提交 103783)。
根据 C++20 标准,您的代码格式错误class.static.mfct#2:
There shall not be a static and a non-static member function with the same name and the same parameter types ([over.load]).
这里也不例外,也有requires
子句来区分成员函数,只是名称相同,参数类型相同。而这正是我们的情况:相同的名称是f
,相同的参数类型是空集。
所以Clang和MSVC在接受代码时是错误的。但是 GCC 的诊断肯定是混乱的。
通过对代码进行一些小的调整(删除非静态成员函数中的 const
并在代码中获取其地址),Clang 和 MSVC 也显示出大问题:
template<bool b>
struct s {
void f() {}
static void f() requires b {}
};
int main() {
s<true>().f();
void (s<true>::*x)() = &s<true>::f;
}