How Do I Unroll a Variadic Template in a Condition?

670 Views Asked by At

I'm looking to unroll a variadic template into separate functions used in the conjunction of an if-statement. Here's an example of what I'm trying to do:

template <typename T, size_t I>
bool bar(const T& param) { return param[I] != 13; }

template <typename T, size_t... ARGS>
void bar(const T& param, const std::index_sequence<ARGS...>&) { 
    if(bar<ARGS>(param) && ...)
    {
        cout << "no matches\n";
    }
    else
    {
        cout << "matched\n";
    }
}

But this gives me the error:

error C3520: ARGS: parameter pack must be expanded in this context

I want the line: if(bar<ARGS>(param) && ...) to unroll to: if(bar<0U>(param) && bar<1U>(param) && bar<2U>(param)) Is there a way I can do this? Or is there an additional adapter that I can use which will accomplish this?

Live Example

3

There are 3 best solutions below

0
max66 On

You need an additional couple of parentheses

// .V.......................V
if( (bar<ARGS>(param) && ...) )

Obviously if your compiler support C++17 (template folding).

Maybe clearer as follows

if( true == (bar<ARGS>(param) && ...) )
0
r3mus n0x On

If your compiler supports C++17's fold-expressions you need to change two things to make it work:

1.Change the order of template parameters in bar so that T can be deduced when I in explicitly specified:

template <size_t I, typename T>
bool bar(const T& param) { return param[I] != 13; }

2.Add a pair of parentheses inside if since they are a mandatory part of a fold-expression:

if ((bar<ARGS>(param) && ...))

Live Example

0
Aconcagua On

So in the sad event that mine does not [support fold expressions] ... Can I do anything?

Well, if that's really the case and the issue was not solely for forgetting the required parentheses, then you can go the way variadic templates needed to be handled before C++17:

template < typename T >
bool bar(T const& param) { return true; }

template <typename T, size_t I, size_t ... II>
bool bar(T const& param) { return param[I] != 13 && bar<T, II...>(param); }

template <typename T, size_t... ARGS>
void bar(T const& param, std::index_sequence<ARGS...> const&)
{
    if(bar<T, ARGS...>(param))
    {
        std::cout << "no matches\n";
    }
    else
    {
        std::cout << "matched\n";
    }
}