Msvc 编译 &(Class::mem) 但 gcc 不编译

Ala*_*lan 3 c++ visual-c++ language-lawyer compiler-bug

我最近学习了指向成员语法的指针,然后编写了如下所示的程序,msvc 可以编译,但 gcc 和 clang 拒绝。

#include <iostream>
#include <type_traits> 
#include <concepts>
struct C
{
    int foo()
    {
    return 5;
    }
};
int main()
{ 
      int (C::*ptr)() = &(C::foo);   //msvc compiles but not gcc and clang  
}  
Run Code Online (Sandbox Code Playgroud)

我想知道哪一个是正确的。现场演示

Hol*_*Cat 8

代码格式错误,MSVC 错误。

\n

[expr.unary.op]/3

\n
\n

如果操作数是命名某个类的非静态或变体成员的限定 ID,而不是显式对象成员函数,则结果类型为 \xe2\x80\x9c,指向类型为\ xe2\x80\x9d 的类成员的指针并指定.mCCTC::\xe2\x80\x8bm

\n

否则,结果的类型为 \xe2\x80\x9c 指向T\xe2\x80\x9d ...

\n
\n

在 中&(C::foo)(C::foo)不是一个限定 IDC::foo将是一个),而是一个主表达式

\n

还有[expr.unary.op]/4更明确​​的:

\n
\n

&仅当使用显式且其操作数是未括在括号中的限定 ID时,才会形成指向成员的指针。

\n
\n

这背后的基本原理是拥有一种用于形成常规(非成员)指针的语法,以防万一您需要一个(而不是成员指针):

\n
#include <type_traits>\n\nstruct A\n{\n    int x;\n};\n\nstruct B : A\n{\n    int x;\n\n    void foo()\n    {\n        auto f = &A::x;\n        static_assert(std::is_same_v<decltype(f), int A::*>);\n\n        auto g = &(A::x);\n        static_assert(std::is_same_v<decltype(g), int *>);\n    }\n};\n
Run Code Online (Sandbox Code Playgroud)\n

MSVC 也接受这个代码,所以我猜它们只是不符合成员函数,而不是数据成员(这没什么大不了的,因为成员函数&(C::foo)总是非法的)。

\n