Is there a syntax for an incomplete nested type without a direct declaration?

The following program generates a diagnostic error.

#include <memory>
class Containing {
    // class Nested;                 // [1]: This line seems required.
    typedef std::shared_ptr<class Nested> Ptr;
    class Nested {
        Ptr & ptr ();
        void foo (const Ptr &p) {
            p->ptr() = ptr()->ptr(); // [2]: Error here without [1]
        }
    };
};
int main () {}

      

Diagnostics performed:

prog.cpp:8:14: error: invalid use of incomplete type 'class Nested'
             p->ptr() = ptr()->ptr();
              ^
prog.cpp:4:35: error: forward declaration of 'class Nested'`
     typedef std::shared_ptr<class Nested> Ptr;
                                   ^

      

However, if I uncomment the forward declaration, the compilation succeeds. I believe the reason is because it Nested

is considered not nested if it is used for shared_ptr<>

. If so, is there any syntax I can use to shared_ptr<>

know I am Nested

nested without directly declaring? Something like:

class Containing {
    typedef std::shared_ptr<class Containing::Nested> Ptr;
    //...

      


This question uses a minimal example to illustrate the problem. The actual structure looks like this:

class Containing {
    typedef std::shared_ptr<class NestedInterface> Ptr;
    class NestedObject {
        Ptr ptr_;
        //...
    };
    class NestedInterface {
        virtual NestedObject & object () = 0;
        void foo (const Ptr &p) {
            // ...
        }
        //...
    };
    class NestedType1 : NestedInterface {
        NestedObject obj_;
        NestedObject & object () { return obj_; }
        //...
    };
    class NestedType2 : NestedInterface {
        Containing &c_;
        NestedObject & object () { return c_.nested_object_; }
        //...
    };
    //...

      

+3


source to share


2 answers


Not. Not.

However, you don't need to avoid forward declarations altogether. It works:

class Containing {
    class NestedInterface;
    typedef std::shared_ptr<NestedInterface> Ptr;
    class NestedObject {
        Ptr ptr_;
        //...
    };
    class NestedInterface {
        // ...
    };
};

      



Sometimes cross-dependencies within classes can make this harder. In this case, all you have to do is not define the referenced classes inline and instead declare other classes out of order, for example:

class Containing {
    class NestedInterface;
    class NestedObject;
    typedef std::shared_ptr<NestedInterface> Ptr;
};
class Containing::NestedObject {
    Ptr ptr_;
    //...
};
class Containing::NestedInterface {
};

      

Note that in general, nested classes in C ++ should not be used whimsically like you might in other languages ​​- you can achieve the same effect with outer classes, and they behave much better. (They don't require defining an outer class.) Only in a few cases were they absolutely necessary. ( std::allocator<T>::rebind<U>

).

+1


source


You should save this declaration here class Nested;

.

Ads relations Ptr

and Nested

is a problem with the chicken and the egg, and the declaration forward - this is the correct way to handle this.



The compiler needs to know that the token Nested

is a class and not something else. The moment the compiler reaches Ptr

, this information is sufficient, and the details of the class are not yet relevant. The compiler then reaches the full declaration Nested

and the details can be used for all future uses of the class.

+1


source







All Articles