在 C++ 中为所有枚举 类 添加方法特化

Add method specialization for all enumeration classes in C++

我的比特流中有以下方法(广义上讲)class:

class BitStream
{
    void StoreBits( unsigned int data, unsigned int numBits );
    
    public:
    template<typename T>
    void WriteType( T value ) { StoreBits( value, sizeof(T) * 8 ) );

    template<>
    void WriteType( float value ) { StoreBits( *(unsigned int*)&value, sizeof(float) * 8 ) );
};

有人在 WriteType 上抛出了一个强类型枚举 class,显然枚举不会自动转换为无符号整数。

如何编写一个使用相同函数命名来处理所有枚举案例的专业化?

这是问题的简单化 - 我有枚举 class 实例被抛出到我必须处理的许多其他 BitStream 成员方法,例如 ReadType、StreamType(读或写)、SmallestRangeWrite () 等

我有可用的 C++17 支持。我知道有 std::is_enum,但我如何才能专注于此,尤其是在编译时?

我能不能这样写:

template<typename T>inline void BitStream::WriteType( T value ) 
{
  if (type_is_enum())
    StoreEnum<T>(value)
  else
    StoreBits( value, sizeof(T) * 8 ) );
}

我需要确保在 T 是枚举时不编译 StoreBits 方法。仅在运行时使用分支避免它是不够的。

测试类型是否为枚举 是否不可转换为 u32。这使您可以区分正常的 enumenum class。如果它是一个枚举但不能转换为 u32,那么它是一个 enum class:

template<typename T>
inline void BitStream::WriteType(T value) 
{
    if constexpr (std::is_enum_v<T> && !std::is_convertible_v<T, u32>)
        // enum class
        StoreEnum<T>(value)
    else
       // normal enum or other type that is convertible to u32
        StoreBits(value, sizeof(T) * 8 ));
}

由于你的StoreEnumStoreBits函数模板不能同时使用,所以你需要在这里使用if constexpr来避免编译时的类型检查。

C++17 的最佳特性(这是我个人的看法)是 constexpr if。这意味着您不需要定义明确的特化。那行得通:

template<typename T>inline void BitStream::WriteType(T value) 
{
    if constexpr (std::is_enum_v<T>)
        StoreEnum<T>(value);
    else
        StoreBits(value, sizeof(T) * 8);
}

使用 constexpr if 很重要,因为如果 T 类型未定义 StoreEnumStoreBits,那么您 运行 有编译失败的风险。