简体   繁体   中英

Nested subclasses in C++

I'm trying to make a nested class which is also a subclass of its parent:

struct X { struct Y : public X {}; };

Unfortunately, this doesn't seem to be allowed in C++, as g++ produces the error

error: invalid use of incomplete type 'struct X'

However, my actual code has X as a templated class:

template<typename T> struct X
{ struct Y : public X {}; };

I get the same message, but this time it's only a warning:

warning: invalid use of incomplete type 'struct X< T >'

My question is: why is the former case illegal, while the templated case just gives a warning? The templated version works exactly as I would expect it to (I can create instances of X<T>::Y , cast them to X<T> , and so on), but does the warning mean that I shouldn't use it? What problems can I expect to run into if I ignore the warning?

To answer the basic question: You get a warning because the template isn't yet instantiated, so it doesn't bother anyone.

The way to fix this, in both cases, would be to define X::Y at the point in which X 's layout is already known, and thus Y 's layout can be properly deduced. You could do:

struct X { struct Y; }
struct X::Y {};

Technically, as far as the compiler is concerned, the layout of the base ( X ) does not need to be known until the template ( X ) is instanciated. And the template ( X ) may not be istantiated before it is fully defined. At which point, it's layout is known.

Simplest way to get an error from your template is to try istantiate Y inside X :

template<typename T> struct X {
    struct Y : public X {};
    Y y;
};

In earlier versions of the complier, there was no warning in the case that you show, but it was added at some point. Here is a discussion from the GCC bugtracker about whether the warning is spurious. There were some uncertainty whether this is allowed by the standard but their conclusion was that it is not allowed.

So, neither case is allowed by the standard, but GCC keeps working with the latter, because it can.

Yam Marcovic Shows how X::Y can be defined in a standard compliant way. Analoguously identical example is shown in the gcc bugtracker.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM