Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Metaprogramming C/C++ using the preprocessor

So I have this huge tree that is basically a big switch/case with string keys and different function calls on one common object depending on the key and one piece of metadata.

Every entry basically looks like this

} else if ( strcmp(key, "key_string") == 0) {
    ((class_name*)object)->do_something();
} else if ( ...

where do_something can have different invocations, so I can't just use function pointers. Also, some keys require object to be cast to a subclass.

Now, if I were to code this in a higher level language, I would use a dictionary of lambdas to simplify this.

It occurred to me that I could use macros to simplify this to something like

case_call("key_string", class_name, do_something());
case_call( /* ... */ )

where case_call would be a macro that would expand this code to the first code snippet.

However, I am very much on the fence whether that would be considered good style. I mean, it would reduce typing work and improve the DRYness of the code, but then it really seems to abuse the macro system somewhat.

Would you go down that road, or rather type out the whole thing? And what would be your reasoning for doing so?

Edit

Some clarification:

This code is used as a glue layer between a simplified scripting API which accesses several different aspects of a C++ API as simple key-value properties. The properties are implemented in different ways in C++ though: Some have getter/setter methods, some are set in a special struct. Scripting actions reference C++ objects casted to a common base class. However, some actions are only available on certain subclasses and have to be cast down.

Further down the road, I may change the actual C++ API, but for the moment, it has to be regarded as unchangeable. Also, this has to work on an embedded compiler, so boost or C++11 are (sadly) not available.

like image 599
bastibe Avatar asked May 17 '12 15:05

bastibe


Video Answer


1 Answers

I would suggest you slightly reverse the roles. You are saying that the object is already some class that knows how to handle a certain situation, so add a virtual void handle(const char * key) in your base class and let the object check in the implementation if it applies to it and do whatever is necessary.

This would not only eliminate the long if-else-if chain, but would also be more type safe and would give you more flexibility in handling those events.

like image 68
Fozi Avatar answered Sep 19 '22 18:09

Fozi