带有 void 参数的显式对象成员函数

问题描述 投票:0回答:1

根据 cppreference 自 C++23 起

对于未使用 cv 限定符或 ref 限定符声明的非静态非虚拟成员函数,其第一个参数如果不是函数参数包,则可以是显式对象参数(用前缀关键字

this
表示) .

这个参数可以是

void
类型吗?当前的编译器允许这样做,但在调用此类成员函数方面存在分歧:

struct A {
    void f(this void) {}
};

// ok everywhere
auto p = &A::f;

int main() {
    // ok in GCC and MSVC
    p();

    // ok in Clang
    A{}.f();
}

Clang 用

 拒绝 
p();

错误:调用的对象类型“void (A::*)()”不是函数或函数指针

GCC 不喜欢

A{}.f();
因为

注意:候选人期望 -1 个参数,提供 0 个

以及 MSVC:

错误 C2660:'A::f':函数不接受 0 个参数

在线演示:https://gcc.godbolt.org/z/zMaqaTTav

这里哪个编译器是正确的?

c++ language-lawyer void c++23 explicit-object-parameter
1个回答
0
投票

就目前标准的编写方式而言,我倾向于认为 Clang 是行为正确的。

根据[dcl.fct]/3

由非依赖类型 void 的单个未命名参数组成的参数列表相当于空参数列表。

this
关键字不会影响参数的类型,该参数仍然是
void
并且保持未命名状态。由于它不在模板内,因此它也不依赖。

[dcl.fct] 的其余部分假设已对声明进行了此调整,但没有再次明确提及,例如在 [dcl.fct]/5 中定义函数的类型时。

因此我认为在this调整之后还应该考虑在参数声明中指定

void
的效果以声明显式对象参数的
[dcl.fct]/6

然后,由于

this void
参数声明已从列表中删除,因此该函数不是显式对象函数,而是不带任何参数的隐式对象函数。

函数类型将为

void()
&A::f
然后形成
void (*A::f)()
类型的成员指针。使用函数调用语法
p()
调用成员指针是不可能的。

使用成员访问表达式

A{}.f()
调用非静态成员函数是可能的。函数定义中的
this
将指向从
A{}
具体化的临时对象。

但是,我不确定这是否真的是理想的行为。

void
参数例外仅存在于 C 向后兼容性。无需将其扩展为
this void
,无论如何,这在 C 中是无效的。相反,我认为它应该像(cv 限定的)
void
参数的所有其他用途一样格式错误。

© www.soinside.com 2019 - 2024. All rights reserved.