Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Empty Pack Variadic Template

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.

like image 908
BiagioF Avatar asked Dec 02 '25 10:12

BiagioF


1 Answers

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>(), ...);
}
like image 124
rmawatson Avatar answered Dec 05 '25 00:12

rmawatson



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!