I am using C++14
(and pretty new to it). I have 3 overloaded functions func
within which another overloaded function do_something
gets called depending on its parent function (func
).
int func(int a) {
bar(a);
foo();
}
int func(int a, float b) {
bar(a);
do_something(b);
foo();
}
int func(int a, float b, char c) {
bar(a);
do_something(b, c);
foo();
}
I see that the functionality within func
is almost the same except which version of do_something
gets called. Is there any way I can make this generic and combine all func
's together?
To begin with, make func
a template that accepts a parameter pack. The int a
argument, the call to bar
and the call to foo
are always there, so that's simple. Let's add a placeholder for do_something
for now.
template <class ...Args>
int func(int a, Args&&... other)
{
bar(a);
// somehow call do_something and do the right thing
foo();
return 0;
}
You want to instantiate and invoke the above template as before:
func(42);
func(42, 1.f);
func(42, 1.f, 'A');
Now let's tackle the call to do_something
. If you simply add it in the middle of the new func
template;
do_something(std::forward<Args>(other)...);
this refuses to compile for func(42)
, i.e., the case with only one argument. Hence, we need a special case for this. One way to achieve this in another level of indirection for do_something
:
// No additional argument case, does nothing:
void do_something_wrapper() {}
// The other two cases
template <class ...Args>
void do_something_wrapper(Args&&... args)
{
do_something(std::forward<Args>(args)...);
}
And now, the placeholder from the func
function template should be:
do_something_wrapper(std::forward<Args>(other)...);