使用与BITSet的initializer_list

Using an initializer_list with bitset

本文关键字:initializer list BITSet      更新时间:2023-10-16

是否有一种使用initializer_list构造bitset

的方法

例如,我想做:

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

但是,当我尝试一下时,我会得到:

错误:无法从'&lt; brace封闭的初始器列表中转换{msb, b, lsb}&gt;'到const std::bitset<3u>

我是否必须使用Shifts来构建unsigned long来初始化foo,或者有办法做到这一点?

没有构造函数可以直接从启动器列表中构造bitset。您需要一个功能:

#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;
}

预期结果:

101

如评论中提到的,也可以使用variadic版本。

#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;
}

使用BITSet的字符串表示形式的简短示例。在某些情况下,此实施可能不是最佳的。

template <typename ... args>
auto make_bitset(args... bools) -> std::bitset<sizeof...(bools)>
{
    char data[] = {bools ? '1':'0'...};
    return std::bitset<sizeof...(bools)>(data, sizeof...(bools));
}
int main()
{
  std::cout << make_bitset(1,1,0,0,1,0, 1) << "n";
  std::cout << make_bitset(1,1,1) << "n";
  std::cout << make_bitset(0,0,0,0) << "n";
}

使用"几乎递归"调用的另一个实现:

template <size_t N, int pos>
void init_bitset(std::bitset<N>&){}
template <size_t N, int pos = 0, typename ...Bits>
void init_bitset(std::bitset<N>& bitset, bool head, Bits ...tail)
{   
   bitset.set(pos, head);
   init_bitset<N, pos + 1>(bitset, tail...);
}
template <typename ... args>
auto make_bitset(args... bools) -> std::bitset<sizeof...(bools)>
{
    std::bitset<sizeof...(bools)> bitset;
    init_bitset(bitset, bools...);
    return bitset;
}
int main()
{
  std::cout << make_bitset(1,1,0,0,1,0, 1) << "n";
  std::cout << make_bitset(1,1,1) << "n";
  std::cout << make_bitset(0,0,0,0) << "n";
}

有关详细信息,请参见编译器资源管理器https://godbolt.org/g/9z2hza

使用C 17

的奖励版本
template <typename ... args>
auto make_bitset(args... bools)
{
    unsigned n = 0;
    static_assert( sizeof...(bools) <= sizeof(n) * 8, "overflow" );
    ((n = n * 2 + static_cast<bool>(bools)), ...);
    return std::bitset<sizeof...(bools)>(n);
}