LRaiz
LRaiz

Reputation: 692

How to forward declare a class to be used in a standard container of unique_ptr

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

Answers (2)

LRaiz
LRaiz

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

Javi
Javi

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

Related Questions