为C ++中的所有枚举类添加方法专门化

问题描述

我的位流类中有以下方法(广义上来说):

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上抛出了一个强类型的枚举类,显然该枚举不会自动转换为无符号整数。

我该怎么写才能使用相同的函数命名来处理所有枚举用例?

这是问题的琐事-我将枚举类实例抛出到我必须处理的许多其他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方法。仅仅在运行时避免使用分支是不够的。

解决方法

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很重要,因为如果StoreEnum类型的StoreBitsT未定义,则有编译失败的风险。

,

测试一下该类型是否为枚举,以及是否不能转换为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以避免编译时进行类型检查。