1

In my GUI system, the main building block is Container class, which can be drawn (= is drawable). However, Container itself is a 'kind of a table' - it contains cells.

Cell class serves for layouting. The number of cells a container has is defined by number of rows and columns.Cell objects are not visible.

And here's the problem. Cell objects cannot be drawn - they contain Container objects, which are drawn by the rules defined in the Cell object (alignment, padding, etc..) when calling cell.draw().

I know this can be easily resolved by using raw pointers to avoid the circular dependency created here, but I wanted to use smart pointers, if possible. However, according to error I'm getting, it's obvious smart pointers have to know the size of the object, unlike raw pointers.

Unique_ptr error

/usr/include/c++/4.8/bits/unique_ptr.h:65:22: error: invalid application of ‘sizeof’ to incomplete type ‘Container’
  static_assert(sizeof(_Tp)>0,

Container.hpp

#include <Cell.hpp> // Causes circular dependency
class Cell; // Causes error: invalid application of ‘sizeof’

class Container
{
// ...
private:
    std::vector<std::unique_ptr<Cell>> cells;
// ...
}

Cell.hpp

#include <Container.hpp> //Causes circular dependency
class Container; // Causes error: invalid application of ‘sizeof’
class Cell
{
// ...
private:
    std::vector<std::unique_prt<Container>> subcontainers;
// ...
}

Is there a nice way how to solve the situation using smart pointers (maybe by redesigning the whole problem solution), or do I have to use raw pointers here?

marc_s
  • 732,580
  • 175
  • 1,330
  • 1,459
sjaustirni
  • 3,056
  • 7
  • 32
  • 50
  • 2
    I don't really see why you would *have* this kind of cycle. What is the *sense* of a Container containing Cells containing Containers? Even if you get it done on a *syntactic* level, it seems like poor design *semantically*... – DevSolar Feb 09 '15 at 17:01
  • Have you considered using references instead of pointers? – Paolo M Feb 09 '15 at 17:04
  • I think you should have one container, containing containers :D each container has a getCells() method – Aitch Feb 09 '15 at 17:05
  • What would you recommend? @DevSolar: The basic idea was to have a drawable object, which could be easily divided in parts, where each part could have more drawable objects. For example, Window itself would be a container, the header would be a container, the body would be as well.. – sjaustirni Feb 09 '15 at 17:05
  • 2
    Drop the circular include and ensure the destructor of the unique_ptr is invoked in a source file (where you include all headers, needed). In other words, you cannot define the destructor in the header. –  Feb 09 '15 at 17:06
  • okay it's an answer now :) – Aitch Feb 09 '15 at 17:10

2 Answers2

5

std::unique_ptr works on forward declared types, but it needs to know the full type for invoking the deleter.

This will bite you if your class uses a compiler-generated destructor. You can get rid of the problem by defining a (possibly empty) custom destructor for the class out-of-line in a source file where the full type definition for the type held by the unique_ptr is visible.

Refer to this answer for the gory details.

Community
  • 1
  • 1
ComicSansMS
  • 51,484
  • 14
  • 155
  • 166
  • I have defined destructor (and even copy constructor and assignment operator) in implementation file. The problem is, however, still there. Any ideas why? – sjaustirni Feb 09 '15 at 17:45
  • @Dundee Not without a more details. Could you post the full error message that you get from the compiler, including all steps of the template instantiation stack? – ComicSansMS Feb 09 '15 at 17:48
  • The problem was a namespace-problem. I forgot to put the forward-declaration in the appropriate namespace. Thank you for your help. Apologies for my idiocy. – sjaustirni Feb 09 '15 at 18:30
0

The answer: I think you should have one container, containing containers :D each container has a getCells() method.

Aitch
  • 1,617
  • 13
  • 24
  • 1
    But save them as smart pointers (shared or unique). You don't want to be copied all the time I think? – Aitch Feb 09 '15 at 17:12