Suppose I have a abstract base class called Node
.
class Node
{
public:
Node() {
leftChild = NULL;
rightChild = NULL;
};
Node * leftChild, *rightChild;
void attach(Node * LC, Node * RC) {
leftChild = LC;
rightChild = RC;
};
};
I also have multiple functions (of which I'll include two for simplicity but in reality this could be any number).
float add(float a, float b){return a+b;}
bool gt(float a, float b){return a>b;}
For each function there is an associated class. The first is as follows.
class BinaryFunction1 : public Node
{
public:
BinaryFunction1() {
};
float(*)(float, float) addition(){
return add
};
}
The second is below.
class BinaryFunction2 : public Node
{
public:
BinaryFunction2() {
};
bool(*)(float, float) greaterthan(){
return gt
};
}
In main I would like to execute something like the below as a way of creating a linked list in the hopes of building an abstract syntax tree.
BinaryFunction1 testBinaryFunction1();
BinaryFunction2 testBinaryFunction2();
testBinaryFunction1.attach(&testBinaryFunction2, &testBinaryFunction2);
dynamic_cast<BinaryFunction2 *>(testBinaryFunction1.leftChild)->greaterthan()(2.0, 4.0)
The dynamic_cast
is really ugly and I see it tripping me up further down the road. Is there a way to avoid this and get rid of it entirely.
As far as I can see Node * leftChild, * rightChild
is really the problem as I believe this is where the implicit down-casting happens. I am unsure how to declare these pointers if I don't know what their types will be at compile time.
My approach would look something like this:
I don't know what exactly you want to do with the function pointers you are currently trying to return, but it's probably got to do with evaluating an expression. That concept can go into the
Node
interface and can be implemented by each concrete type of node. That requires specifying a return type though, and that's not something known at theNode
level. In fact, it's presumably unknown at compile-time in general - invalid user input can obviously not lead to compile-time errors, it will have to lead to run-time errors.std::variant
is a good match here (but limits you to a compile-time set of types, which is probably sufficient).We can then define e.g.
and use everything together like this:
(Note that polymorphy requires pointers or references!)
Play around with it here: https://godbolt.org/z/GNHKCy