const 指向成员的指针是否默认指向一个 int?

Does const pointer-to-member default to pointing to an int?

在玩指向成员的指针时,我遇到了一种似乎有点不一致并且对我来说有点违反直觉的行为。考虑以下虚拟结构:

struct foo {
    int x;
    double d;
};

和以下 main()

int main() {
    int foo::* ptr = &foo::x;
    double foo::* ptr2 = &foo::d;
}

这里我们没有什么不寻常的 - 两个指向 const 成员的指针。代码编译正常。

引起我注意的是,当我们添加const时,情况发生了一点变化。考虑以下代码:

int main() {
    // no int or double after const
    const foo::* ptr = &foo::x;
}

代码在 GCC 8.2.01 上编译良好。请注意,我没有指定指针指向的数据类型。

然而,这段代码:

int main() {
    // notice the only change - "d" instead of "x"
    const foo::* ptr = &foo::d;
}

编译失败,出现以下错误:

error: cannot convert 'double foo::*' to 'const int foo::*' in initialization const foo::* ptr = &foo::d;

这很有趣 - 它表明,默认情况下,const 指向成员的指针被隐式声明为指向某个 int 成员。这是正确的标准行为吗?

值得注意的是,如果我们删除 const,这两行都会产生错误:

int main() {
    foo::* ptr1 = &foo::x;
    foo::* ptr2 = &foo::d;
}

形式为:

error: expected unqualified-id before '*' token

error: 'ptr1' | 'ptr2' was not declared in this scope

所以问题是 - 如果我们不另外指定,标准是否指定 const 指向成员的指针隐式指向 int,或者它是非-标准行为?(GCC 扩展或 GCC 错误)。


1编辑:我正在使用 MinGW 的 GCC - this 特定版本。

So the question is - does the standard specify that const pointer-to-member implicitly points to int if we do not specify otherwise

没有。 GCC 通常会用简单的英语给你答案并拒绝编译(如果你使用 -fpermissive 则发出警告):

error: ISO C++ forbids declaration of 'ptr' with no type

这不是扩展。在 -fpermissive 模式下允许这样做,以保持非常旧的遗留代码的可编译性。

似乎 MinGW-w64 发布的 GCC 没有捕捉到这个错误。不知道是不是故意的

ISO C++ 中的代码不正确,但 "implicit int" 行为由 启用,gcc 自动启用以针对 Microsoft ABI。

您可以使用 -fno-ms-extensions 将其关闭。


我查看了源代码(gcc-9.1.0/gcc/cp/decl.c),结果发现在ms-extensions模式下,implicit int[=31的警告=] 被禁用 - 任何会生成消息 ISO C++ forbids declaration of %qs with no type 的东西实际上都被允许,int 被用于该类型。

这可能是一个比解决它试图解决的任何问题所必需的更大的锤子。例如,您还可以看到与 const *x;const f(); 的差异。

我尝试将 -fno-ms-extensions 添加到我使用 mingw-w64 的一些 "large" Windows 项目的构建中并且没有出现错误,所以也许它会很好练习将此标志作为习惯问题(或者甚至向 mingw-w64 提交补丁以默认关闭它...)。