The following program produces 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 () {}
The produced diagnostic is:
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 that Nested
is assumed to be not nested when it is used for shared_ptr<>
. If that is so, is there a syntax I can use to let shared_ptr<>
know that Nested
is nested without the forward declaration? 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:
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_; }
//...
};
//...
No there isn't.
However, you shouldn't need to avoid the forward declarations at all. This works:
Sometimes cross-dependencies inside the classes might make this hard to do. In that case, all you need to do is to avoid defining the referencing classes inline, and to instead declare the other classes out-of-line, like this:
Note that, in general, in C++, nested classes are not to be used on a whim the way you might in other languages -- you can generally achieve the same effect with outer classes, and they behave much better that way. (They don't require the definition of the outer class.) Only in a few cases have they been absolutely necessary. (
std::allocator<T>::rebind<U>
comes to mind.)