Reputation: 9715
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>()
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.
Upvotes: 3
Views: 1862
Reputation: 1935
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;
}
As pointed out by HolyBlackCat, in c++17 you could just use a fold expression,
template <Action... as>
void applyActions() {
(applyAction<as>(), ...);
}
Upvotes: 5
Reputation: 66200
In C++11, Is there a way to declare a variadic function which accepts an empty parameter pack?
Yes: there is and it's trivial
template <Action...>
void applyActions()
The problem is that, in your case, collide with the function that accept with one or more elements
template <Action a, Action... as>
void applyActions()
and when you call applyActions<as...>();
with a not empty as...
pack, both template match.
The use of a template function with the same name but a different genre of argument (and a default value)
template <typename = void>
void applyActions() {}
it's (IMHO) an extremely smart, cheap and elegant way to solve the termination problem.
Upvotes: 1