Reputation: 527
Lets say I want to only call one function in my code: func(), but depending on which value I give it, have it go STRAIGHT to the correct 'version' of that function?
I know this would be possible to do with if-statements/switch-statements, but then it would have to (inefficiently) check which value was passed. I was hoping there's a pre-compiled way to do it?
Is something like this possible to do in an efficient way?
func(3)
Will execute the third version of func()
func[1]{
cout "One";
}
func[2]{
cout "Two";
}
func[3]{
cout "Three";
}
Upvotes: 1
Views: 3926
Reputation: 21773
Actually, case-switch is very efficient, because even if you have a very large number of targets, it can compile this in the code as a table of jumps, rather than as a chain of ifs - so all parts of the switch will be an equal amount of instructions away.
http://en.wikipedia.org/wiki/Switch_statement#Compilation
If the range of input values is identifiably 'small' and has only a few gaps, some compilers that incorporate an optimizer may actually implement the switch statement as a branch table or an array of indexed function pointers instead of a lengthy series of conditional instructions.* This allows the switch statement to determine instantly what branch to execute without having to go through a list of comparisons.
Furthermore:
1) Don't worry about premature optimization if you haven't identified the code as a bottleneck that's slowing your program down.
2) Why does calling a function with different values make it do entirely different things? Shouldn't it be different functions, instead? (If you want to call a bunch of functions in a loop, you could always create an array of function pointers - look up function pointers)
Upvotes: 2
Reputation: 1950
I believe it could be possible to use a templated function for this.
Eg
template< int subfunc>
void func< subfunc>();
void func<1>();
Something like this should work :)
That way when you call it you say: func<1>();
and it will call the other function.
Just checked it. This solution will not work as the user wishes since the entered value in the chevrons must be a constant/compile-time resolved value.
Upvotes: 0
Reputation: 13510
Since we're tough men using C++ here, I would use a map
from string
(your input) to void *
(represents all the functions), and this way I won't need to count on any specific order of my callable functions in the map. I also don't need to convert the input to a number (in case the input is from the console and it's a string)
#include <map>
#include <string>
#include <iostream> // for cout
using namespace std; // that's the way I like it
int main()
{
map<string, void *> funcs;
funcs["func1"] = (void *)func1;
funcs["func2"] = (void *)func2;
...
string s = myinput();
if (funcs.find(s) != funcs.end()) {
((void (*)())funcs[s])(); // call the function (first casting it to the function's data type
}
else cout << "### Error: function " << s << " doesn't exist in map" << endl;
return 0;
}
Upvotes: 0
Reputation: 10872
You could have an array of function pointers:
int foo_1() {
cout << "One";
}
// ...
auto[] functions = {foo_1, foo_2, foo_3};
and call it with
functions[0]();
Upvotes: 6
Reputation: 1626
When you do func(3)
, where the argument(s) are constant, the compiler will automatically optimize the function if it has no side effects. This means the function may not modify a global variable, member variable, or write to any pointers passed to the function. The if
statements will disappear at runtime.
Upvotes: 0
Reputation: 93561
You can do it with value templates. But if you're doing that, why have a function at all? And why not just have N differently named functions, it will be FAR less confusing when maintaining your code.
Upvotes: -1