Let's say I have some action to perform, at compile time:
enum class Action {A, B};
Now I write a template variadic function which performs a possible combination of action in sequence:
template <Action a>
void applyAction();
template <typename = void>
void applyActions() {}
template <Action a, Action... as>
void applyActions() {
applyAction<a>();
applyActions<as...>();
}
This code is fine. Indeed:
void foo() {
applyActions<Action::A, Action::B>();
}
correctly generates:
call void applyAction<(Action)0>()
call void applyAction<(Action)1>()
GodBolt Example Here
In order to achieve the expansion pack termination, I had to declare the dummy function:
template <typename = void> void applyActions() {}
which is quite "ugly" to me because it gives the possibility to invoke a generic type.
In C++11, Is there a way to declare a variadic function which accepts an empty parameter pack?
Of course, its declaration does not have to bring to call ambiguity with the needed function:
template <Action a, Action... as>
void applyActions();
Something like:
template <Action.. = {}>
void applyActions() {}
Here a not compilable example because of a call ambiguity. But it gives an idea of what I want to achieve.
An alternative way to structure it so you can remove the 'ugly' default is the following, which also removes the recursion and would work with an empty actions parameter pack,
#include <iostream>
using namespace std;
enum class Action {A, B};
template <Action a>
void applyAction()
{
std::cout << "Action " << (int)a << std::endl;
}
template <Action... as>
void applyActions() {
using do_= int[];
(void)do_{0, (
applyAction<as>()
,0)...};
}
void foo() {
applyActions<Action::A, Action::B>();
}
void bar() {
applyActions<Action::B, Action::A>();
}
int main() {
foo();
bar();
return 0;
}
Demo
As pointed out by HolyBlackCat, in c++17 you could just use a fold expression,
template <Action... as>
void applyActions() {
(applyAction<as>(), ...);
}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With