Here is an example:
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;
}
This compiles with gcc
and does not compile with clang
and msvc
. Which compiler is right? Is it a bug of gcc
?
Here is clang
error message:
<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
msvc
error message is the following:
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
This is CWG 1836 and the program is well-formed as per the current wording as explained below.
First note that ->
(and .
) is the member access operator and so we move onto expr.post#expr.ref:
Otherwise, the object expression shall be of class type. The class type shall be complete unless the class member access appears in the definition of that class.
And since ptr_->testFinction()
is within the definition of the class, there is no need for the class-type to be complete here.
Here is the confirmed clang bug:
Clang rejects valid program involving member access operator with incomplete type CWG 1836