在 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
。这使您可以区分正常的 enum
和 enum 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 ));
}
由于你的StoreEnum
和StoreBits
函数模板不能同时使用,所以你需要在这里使用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
类型未定义 StoreEnum
或 StoreBits
,那么您 运行 有编译失败的风险。
我的比特流中有以下方法(广义上讲)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
。这使您可以区分正常的 enum
和 enum 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 ));
}
由于你的StoreEnum
和StoreBits
函数模板不能同时使用,所以你需要在这里使用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
类型未定义 StoreEnum
或 StoreBits
,那么您 运行 有编译失败的风险。