Curious circular inheritance with mix-ins in C++ - c++

What is a good way to unscramble the 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(); /* ... */ }
};
It fails (gcc 4.7.0) because TrafficLight is an incomplete type
when HasImportance tries to inherit from it.
The real problem is that HasImportance needs to know the type returned by
neighbors(). If HasImportance inherits from
Node, then it thinks neighbors() returns a list of
Node*, not TrafficLight*, and consequently doesn't
know that it can call receive_importance() on the items. Similar
problem if HasImportance doesn't inherit at all.
BTW, what I'm trying to do is make a few mix-ins to help define a variety of
different kinds of graphs easily and to unit-test each mix-in separately. For
example, I should be able to define the node class for a graph of traffic lights by just writing
something like class TrafficLight : public HasImportance, HasState<3>,
virtual Node { }.
I've come up with three ways to solve this, but all seem ugly. (1)
static_cast<NodeType*>. (2) TrafficLight passes its
this to HasImportance in its constructor. This way,
HasImportance doesn't need to inherit at all; it just stores a
pointer to (ahem) itself, and the template parameter provides the type of the
pointer. (3) Make Node a class template, like this:
template<class NodeType>
class Node {
public:
list<NodeType*> neighbors() { /* ... */ }
}
class TrafficLight : public HasImportance<Node<TrafficLight>> { /* ... */ }
That compiles and it doesn't introduce a gratuitous copy of this,
but it seems…a little too curious.
Is there a code smell here? Should I approach these graphs in a completely
different way?

(3) but a bit differently.
template <class NodeType>
class Node { ... };
template<class NodeType>
class HasImportance : public virtual Node<NodeType> { ... };
class TrafficLight : public HasImportance<TrafficLight> { ... };
Looks entirely straightforward to me, not more curious than the CRTP itself.

Related

Implement a virtual function for two derived classes, that is the same except for one variable Type

I have an abstract class Node that can either be a Leaf or a NonLeaf. I have written a large function SplitNode. The problem is, this function is basically the same for a Leaf as for a NonLeaf. The only difference being that it operates on the entries vector for Leafs, as opposed to the children vector, for NonLeafs. The code is otherwise identical in both cases. For example in one case I do entries[i]->r to access some Rectangle property, and in the other case I do children[i]->r. So the main difference beyond the 2 variable names, is the type of the actual vector. How am I supposed to implement this, without copying and pasting the same function, implemented slightly differently for Leaf and NonLeaf?
Edit: I also want the SplitNode function to be able to be called recursively.
class Leaf;
class Node
{
public:
Node();
virtual Leaf& ChooseLeaf(const Rectangle& entry_r) = 0; // this makes the Node class Abstract
Rectangle r;
unique_ptr<Node> parent;
};
class Leaf : public Node
{
public:
Leaf();
Leaf& ChooseLeaf(const Rectangle& entry_r) override;
vector<unique_ptr<IndexEntry>> entries;
};
class NonLeaf : public Node
{
public:
NonLeaf();
Leaf& ChooseLeaf(const Rectangle& entry_r) override;
vector<unique_ptr<Node>> children;
};
Dummy illustration of the SplitNode() function:
void SplitNode()
{
// in the Leaf case:
if (this.entries.size() > rtree.M)
{ ... }
// in the NonLeaf case:
if (children.size() > rtree.M)
{ ... }
// in the Leaf case:
entries[0]->r.DoSomething();
// in the NonLeaf case:
children[0]->r.DoSomething();
// Recursion
parent.SplitNode();
...
|
This is a textbook case for a template function. Presuming that the common logic freestanding logic whose only dependency is the vector itself:
template<typename T>
void doSplitNode(T &entries_or_children)
{
for (auto &entry_or_child:entries_or_children)
{
auto &the_r=entry_or_child->the_r;
// Here's your entries[i]->r, or children[i]->r
}
}
// ...
class Leaf : public Node
{
public:
// ...
void SplitNode()
{
doSplitNode(entries);
}
};
class NonLeaf : public Node
{
// ...
void SplitNode()
{
doSplitNode(children);
}
};
Additional work will be needed of the shared logic has additional dependencies. There's no universal solution here, everything depends on the details. Perhaps the template itself can be moved into a class, with both NonLeaf and Leaf multiply-inheriting from it, and then implementing the additional dependencies as virtual/abstract methods.

Is it appropriate to emulate templated data members?

I'm trying to implement a variation of the Observer pattern that buffers different event types and came to an impasse.
This is what I'm trying to go for:
class Foo
{
/* ..... */
std::vector<Base*> buf;
template<typename T>
void newEvent(T ev)
{
/* I give the list of observers to each event.
* There are billions of events coming in for
* each run of the application
*/
buf.push_back(new Event<T>(ev, &observers<T>));
}
/* Illegal, templated data members */
template<typename T>
std::vector<Observer<T>*> observers;
template<typename T>
void attach(Observer<T> obs)
{
/* Each type has its own list of observers */
observers<T>.push_back(obs);
}
/* ..... */
};
Later on when the buffer is flushed...
void Foo::flush()
{
for (Base* ev : buf)
{
ev->notifyAll();
delete ev;
}
}
template <typename T>
class Event : public Base
{
/* ..... */
Event(T t, const std::vector<Observer*>& o):observers(o),payload(t){}
void notifyAll()
{
for (Observer* obs : observers)
obs->onNotify(this->payload);
}
};
The type from the template is just a POD coming in from the outside. When it gets packaged up, I give it the list of observers. Now I could just manually define each type of observer vector in Foo, but I want to be able to support an undefined number of 'Event' types.
I know templated data members of a class are illegal, even in c++14 where there is some more support templated variables.
Does it make sense to keep going down this path? Originally I had the "observers" part statically in each 'Event' type, but I'm trying to get rid of as much global state as I can, for testability.
I'm trying to just move things into a class template, instead, but then I'm having trouble there, too.
template <typename T>
class EventHandler //can't think of a good name for this demon baby
{
public Base* create(T t); //when I create a new event, I need the observer list
public void attach(Observer<T>);
private std::vector<Observer<T>*> observers;
};
class Buffer
{
/* ..... */
EventHandler<EventType1> thing1;
EventHandler<EventType2> thing2;
EventHandler<EventType3> thing3;
template<typename T>
public newEvent(T ev) //I could just explicitly say the type here
{
buf.push_back(thing?.create(ev)); //how to know which one to use?
}
};
I run into the same problem from the other angle :/. I also thought about just switching on the type id but thought it was messy.
One way would be using std::type_index:
class event_handler_base{
public:
virtual ~event_handler_base(){}
};
template<typename T>
class event_handler: public event_handler_base{
public:
void handle(T ev){ /* handle event */ }
};
class my_special_class{
public:
~my_special_class(){
for(auto &&p : handlers)
delete p.second;
}
template<typename T>
void new_event(T ev){
get_handler<T>().handle(ev);
}
template<typename T>
event_handler<T> &get_handler(){
static std::type_index ti(typeid(T));
auto it = handlers.find(ti);
if(it == handlers.end())
it = handlers.emplace(ti, new event_handler<T>()).first;
return dynamic_cast<event_handler<T>&>(*it->second);
}
std::unordered_map<std::type_index, event_handler_base*> handlers;
};
I wouldn't prefer this method if you can figure out a compile-time answer, but it is still interesting. Always prefer compile time cost over run time cost.

C++, a number of classes derive from a class, all the derived classes use a class derived from something else but their base uses that clase's base

I'm sorry the title is so nasty, it's very hard to explain
class BaseState {
protected:
BaseState();
public:
void Some();
void Useful();
void Methods();
};
class UsefulState: public BaseState {
public:
void moreUsefulStuff();
};
class SomeUsefulBase {
protected:
SomeUsefulBase(BaseState* pState) { state = pState; }
void UsefulMethods() { state->Some(); }
void Andthings() { state->Useful(); }
public:
virtual void doSomething() = 0;
protected:
BaseState* state;
};
class SomethingUseful: public SomeUsefulBase {
public:
SomethingUseful(UsefulState* pState): SomeUsefulBase(pState) {
usefulState = pState;
}
virtual void doSomething() { usefulState->moreUsefulStuff();}
protected:
UsefulState* usefulState;
};
then:
SomethingUseful whatever(new UsefulState());
It's not important where things are allocated but there will be a lot of classes derived from SomethingUseful that will use a UsefulState however, all the member functions of SomeUsefulBase will use the state, but as a BaseState
I am hoping there is a better way than using two members (UsefulState and BaseState pointers in the definitions), I've thought of a union and a template, but that would be ugly.
I also don't want to litter my code with casts, I'm wondering if there is a nicer notation.
There will be one UsefulState per operation, and a large tree structure will be formed of various subclasses of SomethingUseful and/or subclasses of SomethingUsefulBase where a UsefulState pointer is expected.
Addendum:
Not sure what's up with SO's syntax highlighting! It seems to be using case to decide if it wants to colour things blue or not.... not sure how that works.
Addendum 2:
In the use this example is derived from there is one state per operation but many things derived from SomeUsefulBase, the derived classes will create each other to form a large tree structure (god I sound noobish) but will all require the use of the derived state.
That sounds like the standard "abstract factory"-type situation:
struct AbstractGadget { virtual ~AbstractGadget() {} };
struct AbstractWidget { virtual ~AbstractWidget() {} };
struct AbstractThingy { virtual ~AbstractThingy() {} };
struct AbstractFactory
{
virtual ~AbstractFactory() {}
virtual std::unique_ptr<AbstractGadget> make_gadget() = 0;
virtual std::unique_ptr<AbstractGadget> make_widget() = 0;
virtual std::unique_ptr<AbstractGadget> make_thingy() = 0;
};
Usage:
struct Gadget1 : AbstractGadget { /* ... */ };
struct Widget1 : AbstractWidget { /* ... */ };
struct Thingy1 : AbstractThingy { /* ... */ };
struct Factory1 : AbstractFactory
{
virtual std::unique_ptr<AbstractGadget> make_gadget()
{
return { new Gadget1; }
}
// ...
};
And so forth for Factory2 and Widget3 etc. There's plenty of potential for eliminating boilerplate code with templates here, too.
Consumers might be given an AbstractFactory & f and call f.make_gadget() etc. to create objects of a suitable type.

What are alternatives to this typelist-based class hierarchy generation code?

I'm working with a simple object model in which objects can implement interfaces to provide optional functionality. At it's heart, an object has to implement a getInterface method which is given a (unique) interface ID. The method then returns a pointer to an interface - or null, in case the object doesn't implement the requested interface. Here's a code sketch to illustrate this:
struct Interface { };
struct FooInterface : public Interface { enum { Id = 1 }; virtual void doFoo() = 0; };
struct BarInterface : public Interface { enum { Id = 2 }; virtual void doBar() = 0; };
struct YoyoInterface : public Interface { enum { Id = 3 }; virtual void doYoyo() = 0; };
struct Object {
virtual Interface *getInterface( int id ) { return 0; }
};
To make things easier for clients who work in this framework, I'm using a little template which automatically generates the 'getInterface' implementation so that clients just have to implement the actual functions required by the interfaces. The idea is to derive a concrete type from Object as well as all the interfaces and then let getInterface just return pointers to this (casted to the right type). Here's the template and a demo usage:
struct NullType { };
template <class T, class U>
struct TypeList {
typedef T Head;
typedef U Tail;
};
template <class Base, class IfaceList>
class ObjectWithIface :
public ObjectWithIface<Base, typename IfaceList::Tail>,
public IfaceList::Head
{
public:
virtual Interface *getInterface( int id ) {
if ( id == IfaceList::Head::Id ) {
return static_cast<IfaceList::Head *>( this );
}
return ObjectWithIface<Base, IfaceList::Tail>::getInterface( id );
}
};
template <class Base>
class ObjectWithIface<Base, NullType> : public Base
{
public:
virtual Interface *getInterface( int id ) {
return Base::getInterface( id );
}
};
class MyObjectWithFooAndBar : public ObjectWithIface< Object, TypeList<FooInterface, TypeList<BarInterface, NullType> > >
{
public:
// We get the getInterface() implementation for free from ObjectWithIface
virtual void doFoo() { }
virtual void doBar() { }
};
This works quite well, but there are two problems which are ugly:
A blocker for me is that this doesn't work with MSVC6 (which has poor support for templates, but unfortunately I need to support it). MSVC6 yields a C1202 error when compiling this.
A whole range of classes (a linear hierarchy) is generated by the recursive ObjectWithIface template. This is not a problem for me per se, but unfortunately I can't just do a single switch statement to map an interface ID to a pointer in getInterface. Instead, each step in the hierarchy checks for a single interface and then forwards the request to the base class.
Does anybody have suggestions how to improve this situation? Either by fixing the above two problems with the ObjectWithIface template, or by suggesting alternatives which would make the Object/Interface framework easier to use.
dynamic_cast exists within the language to solve this exact problem.
Example usage:
class Interface {
virtual ~Interface() {}
}; // Must have at least one virtual function
class X : public Interface {};
class Y : public Interface {};
void func(Interface* ptr) {
if (Y* yptr = dynamic_cast<Y*>(ptr)) {
// Returns a valid Y* if ptr is a Y, null otherwise
}
if (X* xptr = dynamic_cast<X*>(ptr)) {
// same for X
}
}
dynamic_cast will also seamlessly handle things like multiple and virtual inheritance, which you may well struggle with.
Edit:
You could check COM's QueryInterface for this- they use a similar design with a compiler extension. I've never seen COM code implemented, only used the headers, but you could search for it.
What about something like that ?
struct Interface
{
virtual ~Interface() {}
virtual std::type_info const& type() = 0;
};
template <typename T>
class InterfaceImplementer : public virtual Interface
{
std::type_info const& type() { return typeid(T); }
};
struct FooInterface : InterfaceImplementer<FooInterface>
{
virtual void foo();
};
struct BarInterface : InterfaceImplementer<BarInterface>
{
virtual void bar();
};
struct InterfaceNotFound : std::exception {};
struct Object
{
void addInterface(Interface *i)
{
// Add error handling if interface exists
interfaces.insert(&i->type(), i);
}
template <typename I>
I* queryInterface()
{
typedef std::map<std::type_info const*, Interface*>::iterator Iter;
Iter i = interfaces.find(&typeid(I));
if (i == interfaces.end())
throw InterfaceNotFound();
else return static_cast<I*>(i->second);
}
private:
std::map<std::type_info const*, Interface*> interfaces;
};
You may want something more elaborate than type_info const* if you want to do this across dynamic libraries boundaries. Something like std::string and type_info::name() will work fine (albeit a little slow, but this kind of extreme dispatch will likely need something slow). You can also manufacture numeric IDs, but this is maybe harder to maintain.
Storing hashes of type_infos is another option:
template <typename T>
struct InterfaceImplementer<T>
{
std::string const& type(); // This returns a unique hash
static std::string hash(); // This memoizes a unique hash
};
and use FooInterface::hash() when you add the interface, and the virtual Interface::type() when you query.

c++ handling derived class that's self referencing

So suppose I have a tree class like this in c++
class Node{
void addChild(Node*);
/*obvious stuff*/
protected:
Node* parent;
vector<Node*> children
}
class specialNode : public Node{
void addChild(specialNode*);
/*obvious stuff*/
/*special stuff*/
}
Now whenever I access the children in specialTree, I obviously get Node*, not specialNode*.
But this specialNode* has member variables and functions that Node doesn't have.
I can force specialNode to only have take specialNode as children and otherwise break in compile time,
but I still get Node* when accessing children/parent, and I have to cast it whenever I want to use special functions, even in specialNode functions.
Is there any clever, or just any better way to go about this?
Other than literally casting every time?
If you only need SpecialNode objects in your tree (and just want to encapsulate all generic tree functionality in Node) you can make Node a so called "mix-in" class like
template <class N>
class Node : public N {
public:
void addChild(Node<N>*);
protected:
Node<N>* parent;
vector<Node<N>*> children;
};
class SpecialNodeBase {
// Here comes all "special" data/methods for your "special" tree
};
typedef Node<SpecialNodeBase> SpecialNode;
After that you can construct a tree of SpecialNode objects and use all methods from SpecialNodeBase as well as additional tree-managing functions from Node
Because addChild function in your child class is not polymorphism, make it virtual, but overloading functions across base/child members is not allowed, so we have to change the addChild parameter in the child class:
class Node{
virtual void addChild(Node*);
...
}
class specialNode : public Node{
virtual void addChild(Node*);
...
}
Now, it should work.
If you want to access to the childeren variable from the child class (specialNode class), you should cast it. For example:
specialNode* var = static_cast<specialNode*>(children[i]);
Since we declared addChild as a virtual function, then we should use dynamic_cast instead of static_cast if we aren't sure that children[i] is always an instance of specialNode class, and thus it is better to use dynamic_cast:
specialNode* var = dynamic_cast<specialNode*>(children[i]);
if(var != NULL)
{
//...
}
If I understand correctly, the "Mix-in" class solution won't allow you to call addChild from functions implemented by SpecialNodeBaseClass.
You can actually do the following:
template <class recursiveT>
class Base {
public:
Base(dataType data) { populate children with data; }
void addChild() { something base class appropriate; }
protected:
std::vector<recursiveT> children;
};
class Derived: public Base<Derived> {
public:
/* note: the constructor here will actually call the
constuctor of the base class */
Derived(dataType data) : Base<Derived>(data) {}
/* other special functions go here. */
};
This may look a little crazy, but it compiles cleanly for me on several GCC versions so I'm inclined to believe it's not totally wrong-headed. You should now be able to call the functions of Base from inside Derived.
You will definitely have to cast the Node * to a specialNode * at some point, but you can make this clean and easy to manage by doing this in only one place. You could add a member function, say getParent and override it in specialNode, like this:
class Node {
...
virtual Node *getParent() {
return parent;
}
};
class specialNode : public Node {
...
specialNode *getParent() {
return dynamic_cast<specialNode *>(parent);
}
};
Of course, this is assuming that specialNodes always have other specialNodes as parent/children. If you mix Nodes and specialNodes, this obviously won't work.