c++std-bitset

How can I cast an std::bitset<N> to an std::bitset<M>?


If I have an std::bitset<16>, how can I convert it into an std::bitset<32> with the upper bits filled with 0?

std::bitset<16> a = 0xFF00;
std::bitset<32> b = a;  // error

Solution

  • If the number of bits is less than ullong_limits::digits (typically 64), then you can cast via an intermediate unsigned long long:

    #include <limits>
    #include <bitset>
    
    template<size_t M, size_t N>
    std::bitset<M> resize(std::bitset<N> const& in) {
        using ullong_limits = std::numeric_limits<unsigned long long>;
        static_assert(M <= ullong_limits::digits);
        static_assert(N <= ullong_limits::digits);
        return std::bitset<M>(in.to_ullong());
    }
    

    if it isn't, then you need to break down the bitset into ullong pieces, then put them back together:

    #include <limits>
    #include <bitset>
    #include <utility>
    
    namespace detail {
        using ullong_limits = std::numeric_limits<unsigned long long>;
    
        template<size_t N>
        constexpr std::bitset<N> all_ullong_bits() {
            return std::bitset<N>(ullong_limits::max());
        }
    
        /** Resize a bitset, but keeping only the nth ullong */
        template<size_t N, size_t I, size_t M>
        std::bitset<N> resize_nth_ullong(std::bitset<M> const& in) {
            return std::bitset<N>(
                (
                    (in >> (ullong_limits::digits * I)) & all_ullong_bits<M>()
                ).to_ullong()
            ) << (ullong_limits::digits * I);
        }
    
        template<size_t M, size_t N, size_t... I>
        std::bitset<M> resize_helper(std::bitset<N> const& in, std::index_sequence<I...>) {
            return (resize_nth_ullong<M, I>(in) | ... | std::bitset<M>());
        }
    }
    
    template<size_t M, size_t N>
    std::bitset<M> resize(std::bitset<N> const& in) {
        return detail::resize_helper<M>(in, std::make_index_sequence<
            (N + detail::ullong_limits::digits - 1) / detail::ullong_limits::digits
        >{});
    }
    

    In either case, you can then use

    std::bitset<32> b = resize<32>(a);