Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Variadic template combined with default template argument

Suppose I have a class

enum CallbackType
{
    SYNC,
    ASYNC
}


template<CallbackType CB = SYNC, typename... Args>
class Callback
{
}

I would like to be able to optionally specificy the callback type while still being ablet to have variadic template argument. Now I understand that the compiler can't tell them apart, but maybe there is some way to handle the specific case where the first template argument is of CallbackType ?

Callback<int int> //Should be Callback<SYNC, int, int>
Callback<ASYNC, int, int> //Should be Callback<ASYNC, int, int>
like image 792
Andreas Loanjoe Avatar asked Aug 04 '17 11:08

Andreas Loanjoe


1 Answers

There are two aspects of C++, when it comes to variadic templates, that are in conflict with each other in your case:

  1. Defaulted template parameters should not precede non-defaulted template parameters.

  2. Variadic template parameters should not precede non-variadic template parameters.

It is certainly possible, in many situations, to correctly declare, and use, templates whose parameters don't follow these rules, but those situations are not important for the purpose of this question. In your case, what it comes down to is that both of your template parameters want to be the last parameter in their template, for their own individual reasons. That's the problem, in a nutshell.

The easiest way to resolve this conflict is to use an inner template:

template<CallbackType CB = ASYNC>
class CallbackClass {

public:

    template<typename... Args> class Callback
    {
    }
};

Then, your two examples become:

CallbackClass<>::Callback<int, int>

and

CallbackClass<ASYNC>::Callback<int, int>

You'll end up with longer class names, of course. But that's what typedef and using is for. For example:

template<typename ...Args>
using DefaultCallback=CallbackClass<>::Callback<Args...>;

then use

DefaultCallback<int, int>
like image 185
Sam Varshavchik Avatar answered Sep 27 '22 20:09

Sam Varshavchik