英文:
Convert name to constant using switch without ugly code
问题
以下是代码的中文翻译:
/** ---------------------------------------------------------------------------
* @brief 将类型名称从字符串转换为常量类型值
@code
enumType eType = type_g("int32"); assert( eType == eTypeInt32 );
eType = type_g("int8"); assert( eType == eTypeInt8 );
@endcode
* @param stringType 作为字符串发送的类型
* @return {enumType} 类型常量
*/
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;
<details>
<summary>英文:</summary>
I am converting a string to a constant number and that should be done as fast as possible. If possible at compile time. It is used a lot within the code.
Is there a better way to write this type of code?
What it does is to convert the first four character into a 32 bit integer and uses that in a switch to find the constant for 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;
}
**EDIT**
*Based on tips from @Chris Uzdavinis so new solutions is like this*
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; // floatcase hash_type("i128"): eType = eTypeInt128; break; // int128
case hash_type("i256"): eType = eTypeInt256; break; // int254
case hash_type("i512"): eType = eTypeInt512; break; // int512case 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; // pointercase 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; // uint512case 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;
}
</details>
# 答案1
**得分**: 4
以下是您要翻译的代码部分:
```cpp
您可以编写一个简单的函数来执行所有这些重复的工作,然后调用它,大大减少了混乱,使代码更易读,只需为每个枚举编写一个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
}
}
请注意,代码中包含HTML转义字符(例如,<表示小于符号),这些字符需要在实际使用中进行适当处理。
英文:
You can write a simple function to do all that repetitious work, and then call it, vastly reducing the ugliness and making it a lot more readable, just write a case for each enum as you would code it:
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
}
}
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论