调用不完整类型的成员函数在 gcc 中编译,但在 clang 和 msvc 中不编译

Гео*_*нов 5 g++ visual-c++ language-lawyer clang++ c++17

这是一个例子:

struct TestClass {
  void testFunction() const {}
  static TestClass* ptr_;
  constexpr static auto funcPtr = +[](){ ptr_->testFunction(); };
};

TestClass* TestClass::ptr_ = new TestClass();

int main() {
  TestClass::funcPtr();
  delete TestClass::ptr_;
  return 0;
}
Run Code Online (Sandbox Code Playgroud)

这会在gccand 中编译,不会在clangand中编译msvc。哪个编译器是正确的?这是一个错误吗gcc

这是clang错误消息:

<source>:4:46: error: member access into incomplete type 'TestClass'
    4 |   constexpr static auto funcPtr = +[](){ ptr_->testFunction(); };
      |                                              ^
<source>:1:8: note: definition of 'TestClass' is not complete until the closing '}'
    1 | struct TestClass {
      |        ^
1 error generated.
Compiler returned: 1
Run Code Online (Sandbox Code Playgroud)

msvc错误信息如下:

example.cpp
<source>(4): error C2027: use of undefined type 'TestClass'
<source>(1): note: see declaration of 'TestClass'
<source>(4): error C2131: expression did not evaluate to a constant
<source>(4): note: failure was caused by call of undefined function or one not declared 'constexpr'
<source>(4): note: see usage of 'TestClass::<lambda_bdad2d00eade3d9eccb85c581305196c>::operator void (__cdecl *)(void)'
Compiler returned: 2
Run Code Online (Sandbox Code Playgroud)

use*_*570 3

这是CWG 1836,该计划按照当前措辞格式良好,如下所述。

首先请注意->(and .) 是成员访问运算符,因此我们转到expr.post#expr.ref

否则,对象表达式应为类类型。类类型应是完整的,除非类成员访问出现在该类的定义中。

由于ptr_->testFinction()是在类的定义之内,因此此处的类类型不需要完整


这是已确认的 clang 错误

Clang 拒绝涉及类型不完整的成员访问运算符的有效程序 CWG 1836