将enum类与std::bitset一起使用

Using enum class with std::bitset

本文关键字:一起 bitset 类与 std enum      更新时间:2023-10-16

首先,我想要一个普通枚举,而不是基于位的枚举,因为不同枚举的数量将超过任何整数类型。我还想利用C++11enum class的类型安全性。要做到这一点,自然的选择是std::bitset,但我不知道如何将两者结合在一起。

是否需要自定义bitset?如何实现这样一个类?

由于enum classes是枚举的包装器,因此可以将它们强制转换为底层类型使用一些私有继承,您可以选择性地从C++stdlib类导入一些功能,而无需担心Liskov的原理组合产生了更清晰的代码。使用这些功能,我们可以包装std::bitset。下面的代码只包含功能主义者的子集,但它可以进一步扩展。

最大值有一个问题——你不能得到enum class的最大值(或者我错了吗?)。所以我添加了EnumTraits。现在,用户需要用等于enum最大值的常量值max来专门化EnumTraits,然后才能使用类。

#include <bitset>
#include <type_traits>
template<typename T>
struct EnumTraits;
template<typename T>
class EnumClassBitset
{
private:
    std::bitset<static_cast<typename std::underlying_type<T>::type>(EnumTraits<T>::max)> c;
    typename std::underlying_type<T>::type get_value(T v) const
    {
        return static_cast<typename std::underlying_type<T>::type>(v);
    }
public:
    EnumClassBitset() : c()
    {
    }
    bool test(T pos) const
    {
        return c.test(get_value(pos));
    }
    EnumClassBitset& reset(T pos)
    {
        c.reset(get_value(pos));
        return *this;
    }
    EnumClassBitset& flip(T pos)
    {
        c.flip(get_value(pos));
        return *this;
    }
};
enum class BitFlags
{
    False,
    True, 
    FileNotFound,
    Write,
    Read,
    MaxVal
};
template<>
struct EnumTraits<BitFlags>
{
    static const BitFlags max = BitFlags::MaxVal;
};
#include <iostream>
int main()
{
    EnumClassBitset<BitFlags> f;
    f.flip(BitFlags::True);
    f.flip(BitFlags::FileNotFound);
    //f.flip(2); //fails to compile
    std::cout << "Is False? " << f.test(BitFlags::False) << "n";
    std::cout << "Is True? " << f.test(BitFlags::True) << "n";
    std::cout << "Is FileNotFound? " << f.test(BitFlags::FileNotFound) << "n";
    std::cout << "Is Write? " << f.test(BitFlags::Write) << "n";
    std::cout << "Is Read? " << f.test(BitFlags::Read) << "n";
}

不幸的是,由于enums没有太多功能,而且带有enum classes的C++11并不能改善这种情况,一些程序员使用封装在类中的静态映射。绝对是本好书。