Bit packing and unpacking I needed a variadic function to pack and unpack bits into integer types. This is my first attempt:

template&lt;typename T&gt;
constexpr T pack(bool b)
{
    return b;
}

template&lt;typename T, typename... Types&gt;
constexpr T pack(bool b, Types... args)
{
    return (b &lt;&lt; sizeof...(Types)) | pack&lt;T&gt;(args...);
}

template&lt;typename T, typename... Types&gt;
void unpack(T packed, bool&amp; b1)
{
    b1 = packed &amp; 1;
}

template&lt;typename T, typename... Types&gt;
void unpack(T packed, bool&amp; b1, Types&amp;... args)
{
    b1 = packed &amp; (1 &lt;&lt; sizeof...(Types));
    unpack(packed, args...);
}


Usage example:

int main(void)
{
    std::cout &lt;&lt; pack&lt;int&gt;(1, 0, 0, 1, 0, 1, 1, 0) &lt;&lt; std::endl; // 150
    std::cout &lt;&lt; pack&lt;int&gt;(1, 0, 1) &lt;&lt; std::endl; // 5
    int val = pack&lt;int&gt;(1, 0, 1);
    bool b1, b2, b3;
    unpack(val, b1, b2, b3);
    std::cout &lt;&lt; b1 &lt;&lt; " " &lt;&lt; b2 &lt;&lt; " " &lt;&lt; b3 &lt;&lt; std::endl; // 1 0 1
}


Does this code contain any bugs, can it be improved, and are variadic templates used appropriately here (I still don't master their syntax)?
Missing overflow check

One serious flaw that I see in this code is that the user needs to determine the number of parameters to unpack. This is a no go for a function whose output depends on a runtime input. Even worse there is no check that would tell the user that the actual number overflows the number of bits given to be unpacked into.

One possible solution would be to return an std::vector&lt;bool&gt; to fit the whole number.

The other solution would be to retain the current interface but to introduce error notification (by exception or return code).

Unnecessary template parameter

Another thing regarding the unpack function:
It seems that you don't need the Types parameter in the recursion end, so it becomes:

template&lt;typename T&gt;
void unpack(T packed, bool&amp; b1)
{
    b1 = packed &amp; 1;
}


Naming

The function parameter names could be better.
I assume b1 is only appropriate in the top level call of the function. I cannot decide on a better name now, but it should indicate that it is the current bit. Likewise, args should be named remainingBits or something like this.