Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Typedef Circular Dependency

How can I solve the following circular dependency?

typedef boost::variant<int, bool, double, std::string, Structure> Value;
typedef std::list<std::pair<std::string, ValueContainer>> Structure;
typedef std::vector<Value> ValueContainer;

I'm attempting to represent objects from a C api database library in a more C++ form. This database allows one to store values or arrays of values, as well as having a representation for Structures, as follows:

typedef struct ApiStructureMember 
{
    char* name;
    struct ApiValueContainer value;
    struct ApiStructureMember_T* next;
} ApiStructureMember_T;

Finally, a union is used to represent a value, as follows:

typedef struct ApiValue 
{
    union 
    {
        int i;
        const char*   s;
        ...
        struct ApiStructureMember_T* firstStructureMember;
    } value;
} ApiValue_T; 
like image 880
Baz Avatar asked Aug 09 '12 13:08

Baz


People also ask

How do I fix circular dependency error?

To resolve circular dependencies: Then there are three strategies you can use: Look for small pieces of code that can be moved from one project to the other. Look for code that both libraries depend on and move that code into a new shared library. Combine projectA and projectB into one library.

How do you avoid circular dependencies?

To reduce or eliminate circular dependencies, architects must implement loose component coupling and isolate failures. One approach is to use abstraction to break the dependency chain. To do this, you introduce an abstracted service interface that delivers underlying functionality without direct component coupling.

What is meant by circular dependency?

In software engineering, a circular dependency is a relation between two or more modules which either directly or indirectly depend on each other to function properly. Such modules are also known as mutually recursive.

What is circular dependency in dependency injection?

A cyclic dependency exists when a dependency of a service directly or indirectly depends on the service itself. For example, if UserService depends on EmployeeService , which also depends on UserService . Angular will have to instantiate EmployeeService to create UserService , which depends on UserService , itself.


1 Answers

You can't have types mutually containing each other. Think about it: the compiler would get into an infinite loop generating the data.

There are two general patterns: the first is through data types pointing to each other

struct OddNode; // forward declaration

struct EvenNode 
{
    OddNode* prev;
    OddNode* next;
};

struct OddNode
{
    EvenNode* prev;
    EvenNode* next;
};

If you leave away the pointers, and implement the Even and Odd nodes with containment by value, then the compiler can never resolve the definitions.

In general: just draw a picture of how you want to lay out the data, with boxes representing data and lines connecting the various parts. Then replace each box with a class, and each line with a pointer to the corresponding class. If you have a circular dependency somewhere, simply forward declare the classes at the top of your code.

The second circular dependency is through the Curiously Recurring Template Parameter (CRTP)

template<typename T> 
struct Y 
{};

struct X
: 
    public Y<X> 
{};

Your example would be using the CRTP with Structure as X and std::list< ..., Structure> as Y<X>.

like image 158
TemplateRex Avatar answered Nov 05 '22 07:11

TemplateRex