Any C++ class can be first forward declared, and defined only later in the program. Are function-local classes an exception from this rule?

Please consider a simplified program:

auto f() {
    struct A { struct B; };
    return A{};
}

using A = decltype( f() );

struct A::B {};

where struct A::B is only declared inside f(), but defined at the end of the program in the global scope.

EDG says that this is not permitted:

error: class "A::B" cannot be defined in the current scope

GCC crashes with Internal Compiler Error, but both Clang and MSVC accept the program just fine.

Online demo

Which implementation is correct here?

4 Replies 4

FYI: To get the longstanding "real question" behavior, you now have to select "Troubleshooting/Debugging" during the Ask Question process. It's bad.

This is a real question with an objectively correct answer, not a discussion, so please don't use the "Advice" question type.

This is not an Advice question, but an actual technical question. Unfortunately, there is no automated way to fix this, so you will need to delete this post and repost it using the correct post type.

To answer it as an actual technical question:

According to C++23 final draft N4950, This code should not compile. The program is ill-formed.

[class.local]/3 states that

If class X is a local class a nested class Y may be declared in class X and later defined in the definition of class X or be later defined in the same scope as the definition of class X. A class nested within a local class is a local class.

This means that B is also a local class, and this code attempts to define it neither in the definition of class A nor in the same scope as the definition of class A (which is the function scope of f).

The using declaration declares an alias A of the local class A, but it does not change the fact that the class A is a local class. The A introduced by the alias declaration is another name, though it spells "A".

The "internal compiler error" of GCC is not compile error, but a potential GCC bug (that's why it suggests you sending a bug report).


P.S. I'm not quite sure because [class.local]/3 uses the word "may". I did not find any other paragraph addressing this with a stronger tone.

I also found the following code compiles differently among GCC, Clang and MSVC:

auto f() {
    struct A {
        A();
    };
    return A{};
}

using A = decltype(f());

A::A() = default;

int main() {}

godbolt

Thanks for the answers. Unfortunately, I am unable to delete this question (to re-submit it in Troubleshooting/Debugging type) because of "You cannot delete this question as others have invested time and effort into answering it. For more information, visit the help center."

And here is GCC bug report: https://gcc.gnu.org/bugzilla/show_bug.cgi?id=88003. It is marked with "ice-on-valid-code", meaning that GCC team believes that A::B definition is valid.

Your Reply

By clicking “Post Your Reply”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.