使用switch将名称转换为常量,而不使用难看的代码



我正在将字符串转换为常量,这应该尽可能快地完成。如果可能的话,在编译时。它在代码中使用得很多。

是否有更好的方法来编写这种类型的代码?

它的作用是将前四个字符转换为32位整数,并在switch中使用该整数查找name的常量。

/** ---------------------------------------------------------------------------
* @brief Convert type name from string to constant type value
@code
enumType eType = type_g("int32");   assert( eType == eTypeInt32 );
eType = type_g("int8");             assert( eType == eTypeInt8 );
@endcode
* @param stringType type sent as string
* @return {enumType} type constant
*/
constexpr enumType type_g( const std::string_view& stringType )
{
enumType eType = eTypeUnknown;
constexpr uint32_t binary_  = ((uint32_t)'b') + (uint32_t)('i' << 8) + (uint32_t)('n' << 16) + (uint32_t)('a' << 24);
constexpr uint32_t bool_  = ((uint32_t)'b') + (uint32_t)('o' << 8) + (uint32_t)('o' << 16) + (uint32_t)('l' << 24);
constexpr uint32_t double_ = ((uint32_t)'d') + (uint32_t)('o' << 8) + (uint32_t)('u' << 16) + (uint32_t)('b' << 24);
constexpr uint32_t float_ = ((uint32_t)'f') + (uint32_t)('l' << 8) + (uint32_t)('o' << 16) + (uint32_t)('a' << 24);
constexpr uint32_t i128_  = ((uint32_t)'i') + (uint32_t)('1' << 8) + (uint32_t)('2' << 16) + (uint32_t)('8' << 24);
constexpr uint32_t i256_  = ((uint32_t)'i') + (uint32_t)('2' << 8) + (uint32_t)('5' << 16) + (uint32_t)('6' << 24);
constexpr uint32_t i512_  = ((uint32_t)'i') + (uint32_t)('5' << 8) + (uint32_t)('1' << 16) + (uint32_t)('2' << 24);

constexpr uint32_t int8_  = ((uint32_t)'i') + (uint32_t)('n' << 8) + (uint32_t)('t' << 16) + (uint32_t)('8' << 24);
constexpr uint32_t int16_ = ((uint32_t)'i') + (uint32_t)('n' << 8) + (uint32_t)('t' << 16) + (uint32_t)('1' << 24);
constexpr uint32_t int32_ = ((uint32_t)'i') + (uint32_t)('n' << 8) + (uint32_t)('t' << 16) + (uint32_t)('3' << 24);
constexpr uint32_t int64_ = ((uint32_t)'i') + (uint32_t)('n' << 8) + (uint32_t)('t' << 16) + (uint32_t)('6' << 24);
constexpr uint32_t u128_  = ((uint32_t)'u') + (uint32_t)('1' << 8) + (uint32_t)('2' << 16) + (uint32_t)('8' << 24);
constexpr uint32_t u256_  = ((uint32_t)'u') + (uint32_t)('2' << 8) + (uint32_t)('5' << 16) + (uint32_t)('6' << 24);
constexpr uint32_t u512_  = ((uint32_t)'u') + (uint32_t)('5' << 8) + (uint32_t)('1' << 16) + (uint32_t)('2' << 24);
constexpr uint32_t uint_  = ((uint32_t)'u') + (uint32_t)('i' << 8) + (uint32_t)('n' << 16) + (uint32_t)('t' << 24);
constexpr uint32_t pointer_ = ((uint32_t)'p') + (uint32_t)('o' << 8) + (uint32_t)('i' << 16) + (uint32_t)('n' << 24);
constexpr uint32_t rbinary_  = ((uint32_t)'r') + (uint32_t)('b' << 8) + (uint32_t)('i' << 16) + (uint32_t)('n' << 24);
constexpr uint32_t rstring_  = ((uint32_t)'r') + (uint32_t)('s' << 8) + (uint32_t)('t' << 16) + (uint32_t)('r' << 24);
constexpr uint32_t string_  = ((uint32_t)'s') + (uint32_t)('t' << 8) + (uint32_t)('r' << 16) + (uint32_t)('i' << 24);
constexpr uint32_t utf8_  = ((uint32_t)'u') + (uint32_t)('t' << 8) + (uint32_t)('f' << 16) + (uint32_t)('8' << 24);
constexpr uint32_t utf32_  = ((uint32_t)'u') + (uint32_t)('t' << 8) + (uint32_t)('f' << 16) + (uint32_t)('3' << 24);
constexpr uint32_t uuid_ = ((uint32_t)'u') + (uint32_t)('u' << 8) + (uint32_t)('i' << 16) + (uint32_t)('d' << 24);
constexpr uint32_t wstring_  = ((uint32_t)'w') + (uint32_t)('s' << 8) + (uint32_t)('t' << 16) + (uint32_t)('r' << 24);
uint32_t uTypeName = *( uint32_t* )stringType.data(); 
switch( uTypeName )
{
case binary_: eType = eTypeBinary;  break;
case bool_: eType = eTypeBool;  break;
case double_: eType = eTypeCDouble;  break;
case float_: eType = eTypeCFloat;  break;
case i128_: eType = eTypeInt128;  break;
case i256_: eType = eTypeInt256;  break;
case i512_: eType = eTypeInt512;  break;
case int8_: eType = eTypeInt8;  break;
case int16_: eType = eTypeInt16;  break;
case int32_: eType = eTypeInt32;  break;
case int64_: eType = eTypeInt64;  break;
case pointer_: eType = eTypePointer;  break;
case rbinary_: eType = eTypeRBinary;  break;
case rstring_: eType = eTypeRString;  break;
case string_: eType = eTypeString;  break;
case u128_: eType = eTypeUInt128;  break;
case u256_: eType = eTypeUInt256;  break;
case u512_: eType = eTypeUInt512;  break;
case uint_: 
{
if( stringType[4] == '8' ) eType = eTypeUInt8;
else if( stringType[4] == '1' ) eType = eTypeUInt16;
else if( stringType[4] == '3' ) eType = eTypeUInt32;
else if( stringType[4] == '6' ) eType = eTypeUInt64;
else { static_assert("invalid type name"); assert( false ); }
}
break;
case uuid_: eType = eTypeGuid;  break;
case utf8_: eType = eTypeUtf8String;  break;
case wstring_: eType = eTypeWString;  break;
case utf32_: eType = eTypeUtf32String;  break;
default:
assert(false);
}
return eType;
}

编辑

基于来自@Chris Uzdavinis的提示,所以新的解决方案是这样的

namespace detail {
/// helper method used to convert first four characters into 32 bit unsigned integer value
constexpr uint32_t hash_type( std::string_view stringType )
{
uint32_t uHashValue = (uint32_t)stringType[0];
uHashValue += (uint32_t)stringType[1] << 8;
uHashValue += (uint32_t)stringType[2] << 16;
uHashValue += (uint32_t)stringType[3] << 24;
return uHashValue;
}
}
/** ---------------------------------------------------------------------------
* @brief Convert type name from string to constant type value
@code
enumType eType = type_g("int32");   assert( eType == eTypeInt32 );
eType = type_g("int8");             assert( eType == eTypeInt8 );
@endcode
* @param stringType type sent as string
* @return {enumType} type constant
*/
constexpr enumType type_g( const std::string_view& stringType )
{                                                                                                  assert( stringType.length() >= 4 );
using namespace detail;
enumType eType = eTypeUnknown;
uint32_t uTypeName = hash_type( stringType ); 
switch( uTypeName )
{
case hash_type("bina"): eType = eTypeBinary;  break;                        // binary
case hash_type("bool"): eType = eTypeBool;  break;                          // bool
case hash_type("doub"): eType = eTypeCDouble;  break;                       // double
case hash_type("floa"): eType = eTypeCFloat;  break;                        // float
case hash_type("i128"): eType = eTypeInt128;  break;                        // int128
case hash_type("i256"): eType = eTypeInt256;  break;                        // int254
case hash_type("i512"): eType = eTypeInt512;  break;                        // int512
case hash_type("int8"): eType = eTypeInt8;  break;                          // int8
case hash_type("int1"): eType = eTypeInt16;  break;                         // int16
case hash_type("int3"): eType = eTypeInt32;  break;                         // int32
case hash_type("int6"): eType = eTypeInt64;  break;                         // int64
case hash_type("poin"): eType = eTypePointer;  break;                       // pointer
case hash_type("rbin"): eType = eTypeRBinary;  break;                       // rbinary (binary reference)
case hash_type("rstr"): eType = eTypeRString;  break;                       // rstring (string reference)
case hash_type("stri"): eType = eTypeString;  break;
case hash_type("u128"): eType = eTypeUInt128;  break;                       // uint128
case hash_type("u256"): eType = eTypeUInt256;  break;                       // uint256
case hash_type("u512"): eType = eTypeUInt512;  break;                       // uint512
case hash_type("uint"):                                                     // uint8, uint16, uint32, uint64
{
if( stringType[4] == '8' ) eType = eTypeUInt8;
else if( stringType[4] == '1' ) eType = eTypeUInt16;
else if( stringType[4] == '3' ) eType = eTypeUInt32;
else if( stringType[4] == '6' ) eType = eTypeUInt64;
else { static_assert("invalid type name"); assert( false ); }
}
break;
case hash_type("uuid"): eType = eTypeGuid;  break;                          // uuid
case hash_type("utf8"): eType = eTypeUtf8String;  break;                    // utf8
case hash_type("wstr"): eType = eTypeWString;  break;                       // wstring
case hash_type("utf3"): eType = eTypeUtf32String;  break;                   // uft32
default: assert(false);
}
return eType;
}

您可以编写一个简单的函数来完成所有重复的工作,然后调用它,大大减少了丑陋并使其更具可读性,只需为每个enum编写一个case:

enum class enumType : uint32_t {
eTypeBinary, eTypeBool, eTypeCDouble, eTypeCFloat, eTypeInt128, eTypeInt256,
eTypeInt512, eTypeInt8, eTypeInt16, eTypeInt32, eTypeInt64, eTypePointer,
eTypeRBinary, eTypeRString, eTypeString, eTypeUInt128, eTypeUInt256, eTypeUInt512,
eTypeUInt8, eTypeUInt16, eTypeUInt32, eTypeUInt64, eTypeGuid, eTypeUtf8String,
eTypeWString, eTypeUtf32String, eTypeUnknown,
};
constexpr uint32_t myHash(std::string_view sv) {
uint32_t result = 0;
for (int i = 0; i < sv.size(); ++i) {
result += sv[i] << (8*i); 
}
return result;
}
constexpr enumType type_g(std::string_view stringType )
{
using enum enumType;
switch(myHash(stringType))
{
case myHash("bina"): return eTypeBinary;
case myHash("bool"): return eTypeBool;
case myHash("doub"): return eTypeCDouble;
// ...
default:
throw "unhandled"; // compile time err if reached in constexpr
}
}

相关内容

  • 没有找到相关文章

最新更新