c++nestedinner-classesnested-classouter-classes

Nested class definition outside outer class's, while outer class contains instance of inner class


C++

How can I put the definition of an inner (nested) class outside its outer (enclosing) class's definition, where the outer class has at least one instance of the inner class as a data member? I searched but the most relevant SO answer I found, Nested Class Definition in source file, does not have an example where the outer class has an inner object as a data member. I followed that answer, as far as declaring but not defining the inner class inside the outer class's definition is concerned, but my code is still broken:

struct Outer
{
    struct Inner;
    Inner myinner;
    Outer() : myinner(2) {}
};

struct Outer::Inner
{
    Inner(int n) : num(n) {}
    int num;
};

int main()
{
    Outer myouter;
}

It gives the error error C2079: 'Outer::myinner' uses undefined struct 'Outer::Inner' in VC11.

And why doesn't the broken code have an effect equivalent to that of the version in which Inner is defined within Outer's definition, like in the following working code?

struct Outer
{
    struct Inner
    {
        Inner(int n) : num(n) {}
        int num;
    } myinner;
    Outer() : myinner(2) {}
};

Solution

  • This is a red flag, but you can do it using a fake template.

    template< typename = void >
    struct Outer_temp
    {
        struct Inner;
        Inner myinner;
        Outer_temp() : myinner(2) {}
    };
    
    typedef Outer_temp<> Outer; // Hide template from user.
    
    template< typename v >
    struct Outer_temp< v >::Inner
    {
        Inner(int n) : num(n) {}
        int num;
    };
    
    int main()
    {
        Outer myouter;
    }
    

    Inner inside the template is a dependent type, so it does not need to be complete as you define an instance, in a member or any other context. It only needs to be complete once the instantiation happens, in this case from main.

    I can't imagine a good reason to do this, but there it is.

    Nested classes should not be used for the sake of program organization. Nesting suggests a conceptual dependency, "Inner cannot exist except in a context provided by Outer." Although it is common, for example, for a container node class to be nested within the container, this can cause problems. The SCARY idiom is a design style that repudiates such organization and gains improved genericity.

    TL;DR: define the two classes independently and link them with a nested typedef.