Reputation: 1
I have encountered a problem for which I'm unable to find an easily maintainable and readable solution to.
I'm basically writing a "master state machine" I have a node which receives enums from 3 other slave nodes, which independently do their thing and come to a certain state and report it to the master
Slave 1 outputs one of the enums:
enum slave1 {
A,
B
}
Slave 2 outputs one of the enums:
enum slave2 {
1,
2
}
Slave 3 outputs one of the enums:
enum slave3 {
a,
b,
c
}
It is important to note that i don't have any control over the behavior, structure and outputs of the slave nodes
Now, based on the values received my master node has the following logic
val_slave_1 = getSlave1Val();
val_slave_2 = getSlave2Val();
val_slave_3 = getSlave3Val();
switch(val_slave_1):
case A:
switch(val_slave_2):
case 1:
switch(val_slave_3):
case a: {do Z}
case b: {do Y}
case c: {do X}
case 2:
switch(val_slave_3):
case a: {do W}
case b: {do V}
case c: {do U}
case B:
switch(val_slave_2):
case 1:
switch(val_slave_3):
case a: {do T}
case b: {do S}
case c: {do R}
case 2:
switch(val_slave_3):
case a: {do Q}
case b: {do P}
case c: {do O}
The advantages of this code are -
The problem with this code is that it -
My question to you all is that is there a better way to do this? I read a lot of places which said polymorphism is often a good way to solve switch statements but I tried making my code polymorphic and can't seem to nail down a solution. While a lot of people gave simple examples of vehicles and cats, it doesn't seem like I can apply it to my problem.
Another important note: it may be obvious but I'll still write it. It doesnt matter what order I write switch case statements in. To maintain sanity I will choose to write it in the order of most to least enums to save lines of code (I think)
The closest thread I found to this problem is -
Is there any design pattern to avoid a nested switch case?
But is there a better way to do this than maintaining a dictionary of enums to map to a function?
Upvotes: 0
Views: 60
Reputation: 1448
Because your enum values are small, a map from enum combinations to functions could just be an array. When you have 3, 4, and 7 values (i.e. 2, 2, and 3 bits, respectively), you could use a single byte for indexing into an array of function pointers. Something like this:
using Handler = void (*)();
std::array<Handler, 128> handlers = { doA, doB, doB, doG, nullptr, ..., doFoo };
int v1 = slave1(); // 0-6
int v2 = slave2(); // 0-3
int v3 = slave3(); // 0-2
int index = (v2 << 5) | (v1 * 3 + v3);
handlers[index]();
If your enum values are not continuous from 0 to n, you might have to remap them to that.
You might want to come up with a clever way of populating the array, since manually recalculating the indexes when something changes might take a while. One way I can think of right now is a constexpr
function that takes a number of structs that each contain the enum values and a function pointer, populating an array from those. The structs would calculate the index, the function would just assign function pointers from indexes. Or something like that.
Upvotes: 1