Reputation: 692
Is it possible to avoid having full class definition visible when using it in standard container of smart pointers? For example I can't get the following to compile:
#include <memory>
#include <map>
class Foo;
class Bar {
public:
Bar();
std::map<int, std::unique_ptr<Foo>> myMap;
};
The Clang compiler seems to insist on having full definition of Foo
available when compiling Bar
. Is there a technique I could use to avoid having to include Foo.h?
Edit1:
error: invalid application of 'sizeof' to an incomplete type 'Foo': static_assert(sizeof(_Tp) > 0, "default_delete can not delete incomplete type");
Edit2: No it is not a duplicate of is std::unique_ptr required to know the full definition. Just using unique_ptr does not necessarily requires full definition, but using it inside of standard container introduces additional wrinkles.
Edit3: It turns out I can achieve (almost) what I want by introducing a base class with a virtual destructor. Then a class that has a container of smart pointers to base class will compile w/o a problem. Nothing else has to be present in base class and base class must be fully visible. This way all complexities of derived classes may be hidden when container is compiled.
Upvotes: 3
Views: 1553
Reputation: 692
Even though strict forward declaration would not compile a container of smart pointers, it is still possible to solve most practical needs and avoid exposing a complete class when defining a user class with a container. Just introduce a base class with public virtual distractor and have it visible.
in fooBase.h
class FooBase {
public virtual ~FooBase();
};
in bar.h
#include "foobase.h"
#include <memory>
#include <map>
class Bar {
...
std::map<int, std::unique_ptr<FooBase>> myMap;
}
When Foo is derived from FooBase and placed in its own header file changes to Foo would no longer necessitate recompilations of Bar.
Upvotes: 0
Reputation: 3610
You have yo make the Foo destructor and constructors public. IF you are having othe errors please post them, since it is hard to tel from your initial post. The following code compiles:
#include <memory>
#include <map>
class Foo;
class Bar {
public:
Bar () {};
std::map<int, std::unique_ptr<Foo> > myMap;
};
class Foo {
public:
Foo () {};
~Foo () {};
};
int main ()
{
Bar b;
}
EDIT: check these other posts:
Forward declaration with unique_ptr?
Is std::unique_ptr<T> required to know the full definition of T?
Upvotes: -1