The following code compiles fine:
#include <cstddef>
struct A {
char a;
static constexpr int off(void) { return offsetof(A, a); }
static constexpr int (*off_p)(void) = off;
};
The following seemingly similar code that just uses lambda for short, doesn't compile:
#include <cstddef>
struct A {
char a;
static constexpr int (*off_p)(void) =
[](void) static constexpr ->int { return offsetof(A, a); };
};
$ g++ -std=c++23 bad.cpp
In file included from /usr/include/c++/13/cstddef:50,
from bad.cpp:1:
bad.cpp: In static member function ‘A::<lambda()> static’:
bad.cpp:5:74: error: invalid use of incomplete type ‘struct A’
So basically I have 2 separate questions, since I don't understand what's going on here.
- Why in the first case the use of incomplete type is allowed?
- Why in the second case the use of incomplete type is NOT allowed?
There's a finite list of places inside the member specification of a class (i.e. before the closing brace), where it is considered complete:
Now, while we may be tempted to think that a function body or default member initializer applies to the lambda case, they in fact do not. To start with, default member initializers appear in non-static members only (that's just how the standard terminology is laid out, static member initializers are defined as something else).
And as for "function body", note that the bullet refers to a relevant section where the grammar production of a function body is defined:
On the other hand, the grammar for a lambda expression doesn't reuse the
function-body
grammar at all:So with a lambda, we are in fact not in a complete class context, so paragraph 8 forces the compiler to treat
A
as incomplete.