Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How do you static_assert the values in a parameter pack of a variadic template?

I'm creating a variadic template.
Let's say I have something like this:

template<typename T, T ... Numbers>
class Sequence final {

    // Unpack parameter pack into a constexpr array
    constexpr static T count = sizeof...(Numbers);        
    constexpr static T numbers[count] = { Numbers... };

    // ...
}

Instances of this class can be instantiated like:

Sequence<uint32_t, 1, 2, 3, 42, 25> seq;

I'd like to make sure at compile time using a static_assert that the numbers parameter pack only contains specific numbers. For the sake of this example, let's say I only want to allow 0 or 1.

So I'd like to do something like:

for (size_t i = 0; i < count; i++) {
    static_assert(numbers[i] == 1 || numbers[i] == 0, "Only ones and zeroes are allowed.");
}

But obviously, static_assert doesn't work with a for loop. I'm pretty sure there must be some sort of syntax for this but I haven't been able to figure it out.

I'd prefer to use something that compiles with a C++11 compiler (or perhaps a C++14 compiler, if it isn't doable in C++11).

like image 647
Venemo Avatar asked Apr 29 '16 08:04

Venemo


People also ask

What is Variadic template in C++?

Variadic templates are class or function templates, that can take any variable(zero or more) number of arguments. In C++, templates can have a fixed number of parameters only that have to be specified at the time of declaration.

What is the use of Variadic templates?

With the variadic templates feature, you can define class or function templates that have any number (including zero) of parameters. To achieve this goal, this feature introduces a kind of parameter called parameter pack to represent a list of zero or more parameters for templates.


1 Answers

I'll throw in @Columbo's bool_pack trick.

template<bool...> struct bool_pack;
template<bool... bs> 
using all_true = std::is_same<bool_pack<bs..., true>, bool_pack<true, bs...>>;

static_assert(all_true<(Numbers == 0 || Numbers == 1)...>::value, "");

Extract the expression into a constexpr function if it gets complex.

like image 125
T.C. Avatar answered Oct 01 '22 02:10

T.C.