2

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.

Community
  • 1
  • 1
LRaiz
  • 667
  • 7
  • 18
  • 2
    `unique_ptr` might be a typo (besides other typos) –  Sep 11 '14 at 19:13
  • [Please show your real code](http://coliru.stacked-crooked.com/a/4b71c4045c07b58e). – Andy Prowl Sep 11 '14 at 19:14
  • What is the error? Can you fix the typos in your code? – Piotr Skotnicki Sep 11 '14 at 19:45
  • Typos fixed. Added errors produced by compiling actual code. – LRaiz Sep 11 '14 at 19:51
  • There are more tipos Bar constructor instantiation `Bar() {}` and ; at the end of the Bar class declaration – Javi Sep 11 '14 at 19:59
  • I don't think my reputation deserves to be decreased just because there is an insignificant typo or because someone guessed (incorrectly) that the question was asked and answered previously. – LRaiz Sep 11 '14 at 23:55
  • [https://stackoverflow.com/questions/9954518/stdunique-ptr-with-an-incomplete-type-wont-compile](This answer is actually perfectly relevant), if you declare a destructor the compiler won't generate one and you can define it where Foo is fully defined. – radman Nov 16 '17 at 13:41

2 Answers2

0

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.

LRaiz
  • 667
  • 7
  • 18
-1

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?

Community
  • 1
  • 1
Javi
  • 3,440
  • 5
  • 29
  • 43
  • 1. Adding code that "works" does not explain why it does not in the context of OP. 2. public constructor/destructor has nothing to do with that, the question is about full/forward declaration with `unique_ptr` – Piotr Skotnicki Sep 11 '14 at 19:52
  • Check my eddited answer. I have added some references that reply what he asked about. Also, he is saying that he gets an error in the code so I solved it. And public constructor/destructor is required. Otherwise that code will not compile (g++ 4.8.2) – Javi Sep 11 '14 at 19:54
  • Yes he posted it while I was writing :) Believe it or not, his code do not compile until I include the public: keyword. I am double checking it – Javi Sep 11 '14 at 19:58
  • the problem relates to associating unique_ptr with destructor of type T which happens statically, hence, the destructor of Bar needs to know destructor of Foo. And you did this by adding declaration of Foo, but the question is whether that declaration is necessary – Piotr Skotnicki Sep 11 '14 at 20:01
  • I know, probably I was too fast with the answer. That is why in the edit I added the references to other similar posts. – Javi Sep 11 '14 at 20:03