Recently I was working on C++ code that had bunch of if-else statements that resembled following.
As you can see there is common code however datatype of couple of variables varies based on the condition.
You can see the pattern here! So moved the common code to a function template of the form
So far so good. However in order to invoke the right function I still needed to use if-else block which was an eye-sore
To avoid if-else block, I decided to use a jump-table using map where key would be datatype (string) and value would be function to be invoked.
In addition to UConfigParam type variables, I needed to add support for other variables of the form UStateVar. To achieve this, I simply added more entries to the ProcessFuncMap without changing code for function invocation or piling up if-else code block.
So there you see, using a combination of function templates and a jump table at run time dynamic declaration of variables is achievable.
If there are known design patterns or other techniques that help achieve same in C++ I'd like to hear about them.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
std::string type = get_type(); | |
if (type == "int") { | |
UParamInt p; | |
..... | |
..... | |
int v; | |
..... | |
..... | |
} else if (type == "float") { | |
UParamFloat p; | |
..... | |
..... | |
float v; | |
..... | |
..... | |
} else if (type == "bool") { | |
UParamBool p; | |
..... | |
..... | |
bool v; | |
..... | |
..... | |
} else if (type == "string") { | |
UParamString p; | |
..... | |
..... | |
string v; | |
..... | |
..... | |
} |
You can see the pattern here! So moved the common code to a function template of the form
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
template<typename T, typename U> | |
int process_param(void) | |
{ | |
T p; | |
..... | |
..... | |
U v; | |
..... | |
..... | |
} |
So far so good. However in order to invoke the right function I still needed to use if-else block which was an eye-sore
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
if (type == "int") { | |
process_param<UParamInt, int>(); | |
} else if (type == "float") { | |
process_param<UParamFloat, float>(); | |
} else if { | |
.... | |
} |
To avoid if-else block, I decided to use a jump-table using map where key would be datatype (string) and value would be function to be invoked.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
typedef int (*ProcessParamFuncPtr)(void); | |
typedef std::map< std::string, ProcessParamFuncPtr> ProcessFuncMap; | |
// Initialize map with appropriate functions for the datatype. | |
ProcessFuncMap map = boost::assign::map_list_of | |
("int64", process_param< UConfigParamInt, int >) | |
("bool", process_param< UConfigParamBool, bool >) | |
("float", process_param< UConfigParamFloat, float >) | |
("string", process_param< UConfigParamString, std::string>); | |
// Invoke function based on the datatype | |
std::string type = get_type(); | |
ProcessFuncMap::iterator it = map.find(type); | |
if (it != map.end()) { | |
ProcessParamFuncPtr fptr = (*it).second; | |
int ret = fptr(); | |
} | |
In addition to UConfigParam type variables, I needed to add support for other variables of the form UStateVar. To achieve this, I simply added more entries to the ProcessFuncMap without changing code for function invocation or piling up if-else code block.
So there you see, using a combination of function templates and a jump table at run time dynamic declaration of variables is achievable.
If there are known design patterns or other techniques that help achieve same in C++ I'd like to hear about them.