Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to declare a self-referential container in C++?

For a typedef of a struct in C, I can't do this:

typedef struct {
    unsigned id;
    node_t *left;
    node_t *right;
} node_t;

because node_t is not known until it is defined, so it can't be used in its own definition. A bit of a Catch-22. However, I can use this workaround to make the desired self-referential type:

typedef struct node_s node_t;
struct node_s {
    unsigned id;
    node_t *left;
    node_t *right;
};

Similarly, I would like to do something like this for a C++ container referring to itself:

typedef pair<unsigned, pair<node_t *, node_t * > > node_t;

but of course, the compiler complains that it's never heard of node_t before it's defined node_t, as it would for the struct typedef above.

So is there a workaround like for the struct? Or some better way to do this? (And no, I don't want to use void pointers.)

like image 984
Mark Adler Avatar asked Dec 30 '15 07:12

Mark Adler


People also ask

What is self-referential structure in C?

Self Referential structures are those structures that have one or more pointers which point to the same type of structure, as their member. In other words, structures pointing to the same type of structures are self-referential in nature. Example: CPP.

How do you represent self-referential structure?

It should be remembered that a pointer to a structure is similar to a pointer to any other variable. A self referential data structure is essentially a structure definition which includes at least one member that is a pointer to the structure of its own kind.

What is self-referential structure explain it with an example?

A self-referential structure is one of the data structures which refer to the pointer to (points) to another structure of the same type. For example, a linked list is supposed to be a self-referential data structure. The next node of a node is being pointed, which is of the same struct type.


2 Answers

You can self-reference a struct pointer if you name it (i.e. typedef struct <name> {...}). I usually use the following idiom:

typedef struct _node_t { // "Temporary" name "_node_t"
    unsigned id;
    struct _node_t *left; // Have to use "struct _node_t"
    struct _node_t *right;
} node_t; // "Final" name

That basically applies the previous answers to actual code.

like image 87
Matthieu Avatar answered Oct 15 '22 15:10

Matthieu


You can do it like this:

struct node_t : std::pair<unsigned, std::pair<node_t *, node_t * > >
{};

After struct node_t the compiler knows that the type with name node_t exists, similar to a forward declaration.

like image 24
Rabbid76 Avatar answered Oct 15 '22 14:10

Rabbid76