Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Using an initializer_list with bitset

Is there a way to use an initializer_list to construct a bitset?

For example I'd like to do:

const auto msb = false;
const auto b = true;
const auto lsb = false;
const bitset<3> foo = {msb, b, lsb};

But when I try this I get:

error: could not convert {msb, b, lsb} from '<brace-enclosed initializer list>' to const std::bitset<3u>

Do I have to use shifts to construct an unsigned long to initialize foo, or is there a way to do this that I don't know about?

like image 526
Jonathan Mee Avatar asked Feb 07 '23 17:02

Jonathan Mee


1 Answers

There is no constructor to directly construct a bitset from an initialiser list. You'll need a function:

#include <bitset>
#include <initializer_list>
#include <iostream>

auto to_bitset(std::initializer_list<bool> il)
{
    using ul = unsigned long;
    auto bits = ul(0);
    if (il.size())
    {
        auto mask = ul(1) << (il.size() - 1);

        for (auto b : il) {
            if (b) {
                bits |= mask;
            }
            mask >>= 1;
        }
    }
    return std::bitset<3> { bits };

}

int main()
{
    auto bs = to_bitset({true, false, true});

    std::cout << bs << std::endl;
}

expected results:

101

As mentioned in comments, a variadic version is also possible.

#include <bitset>
#include <iostream>
#include <utility>

namespace detail {
    template<std::size_t...Is, class Tuple>
    auto to_bitset(std::index_sequence<Is...>, Tuple&& tuple)
    {
        static constexpr auto size = sizeof...(Is);
        using expand = int[];
        unsigned long bits = 0;
        void(expand {
            0,
            ((bits |= std::get<Is>(tuple) ? 1ul << (size - Is - 1) : 0),0)...
        });
        return std::bitset<size>(bits);
    }
}

template<class...Bools>
auto to_bitset(Bools&&...bools)
{
    return detail::to_bitset(std::make_index_sequence<sizeof...(Bools)>(),
                             std::make_tuple(bool(bools)...));
}

int main()
{
    auto bs = to_bitset(true, false, true);

    std::cout << bs << std::endl;
}
like image 78
Richard Hodges Avatar answered Feb 19 '23 20:02

Richard Hodges