Curious looping inheritance using mixing in C ++

What is a good way to impose circular inheritance here?

class Node { // ... public: list<Node*> neighbors() { /* ... */ } void update() { } } template<class NodeType> class HasImportance : public virtual NodeType { double m_importance = 0.0; public: void receive_importance(double imp) { /* ... */ } void give_importance() { for (auto neighbor : this->neighbors()) neighbor->receive_importance(m_importance /* ... */); } }; class TrafficLight : public HasImportance<TrafficLight>, virtual Node { public: list<TrafficLight*> neighbors() { ... } void update() { give_importance(); /* ... */ } }; 

Error (gcc 4.7.0) because TrafficLight is an incomplete type when HasImportance tries to inherit it.

The real problem is that HasImportance needs to know the type returned by neighbors() . If HasImportance inherits from Node , then it thinks that neighbors() returns a list of Node* , not TrafficLight* , and therefore do not know what it can call receive_importance() for elements. Similar if HasImportance does not inherit at all.

By the way, I am trying to make several mixes to help identify many different types of graphs to easily and individually test each mixture separately. For example, I would have to define a node class for a traffic light graph by simply writing something like class TrafficLight : public HasImportance, HasState<3>, virtual Node { } .

I have three ways to solve this, but everyone seems ugly. (1) static_cast<NodeType*> . (2) TrafficLight passes this to HasImportance in its constructor. Here, HasImportance need not be inherited at all; it just stores the pointer to (s) itself, and the template parameter provides a pointer type. (3) Create a Node template template, for example:

 template<class NodeType> class Node { public: list<NodeType*> neighbors() { /* ... */ } } class TrafficLight : public HasImportance<Node<TrafficLight>> { /* ... */ } 

It compiles and doesn't introduce a free copy of this , but it seems ... a little too curious.

Is there a smell of code here? Should I approach these charts in a completely different way?

+6
source share
1 answer

(3), but a little different.

 template <class NodeType> class Node { ... }; template<class NodeType> class HasImportance : public virtual Node<NodeType> { ... }; class TrafficLight : public HasImportance<TrafficLight> { ... }; 

It looks absolutely straightforward to me, no more curious than CRTP itself.

+1
source

Source: https://habr.com/ru/post/919585/


All Articles