我有一个带有enum变量的类,我想对该enum进行字符串化。因此,我添加了typeValue使用字符串化的值。此外,我添加了单独的类来获得字符串化的值,但我不能以正确的方式传递变量。代码如下:
#include <iostream>
#include <string>
#include <algorithm>
#define stringify(name) #name
struct MyClass
{
enum class TYPE
{
UNKNOWN = 0,
CLIENT,
SERVER
};
MyClass(TYPE t)
:_type(t)
{
}
TYPE type()
{
return _type;
}
inline static const char* typeValue[10] =
{
stringify(TYPE::UNKNOWN),
stringify(TYPE::CLIENT),
stringify(TYPE::SERVER)
};
private:
TYPE _type;
};
struct EnumStringify
{
/**
* Get enum type string by value
*/
template <class EnumType>
static std::string getEnumTypeName(const EnumType& t, const char (*typeValues)[10])
{
std::string s(typeValues[static_cast<int>(t)]);
return (s.size()) ? s.substr(s.find_last_of(":") + 1) : "";
}
};
int main()
{
MyClass a(MyClass::TYPE::CLIENT);
std::cout << EnumStringify::getEnumTypeName<MyClass::TYPE>(a.type(), MyClass::typeValue).c_str();
}
错误的事情发生了:
main.cpp:55:90: error: no matching function for call to ‘EnumStringify::getEnumTypeName(MyClass::TYPE, const char* [10])’
std::cout << EnumStringify::getEnumTypeName<MyClass::TYPE>(a.type(), MyClass::typeValue).c_str();
^
main.cpp:45:21: note: candidate: template static std::string EnumStringify::getEnumTypeName(const EnumType&, const char (*)[10])
static std::string getEnumTypeName(const EnumType& t, const char (*typeValues)[10])
^~~~~~~~~~~~~~~
main.cpp:45:21: note: template argument deduction/substitution failed:
main.cpp:55:90: note: cannot convert ‘MyClass::typeValue’ (type ‘const char* [10]’) to type ‘const char (*)[10]’
std::cout << EnumStringify::getEnumTypeName<MyClass::TYPE>(a.type(), MyClass::typeValue).c_str();
请帮我改正一下。可以使用typedef会更好吗?
两个问题:
const char(*name)[]
定义了一个指向const char
数组的指针,而不是字符串。MyClass::typeValue
是const char* (&)[10]
类型的,所以它不能隐式地转换为指向该数组的指针。
如此:
class MyClass{
//...
constexpr static const char* typeValue[10] = {
stringify(TYPE::UNKNOWN),
stringify(TYPE::CLIENT),
stringify(TYPE::SERVER)
};
private:
TYPE _type;
};
struct EnumStringify
{
/**
* Get enum type string by value
*/
template <class EnumType>
static std::string getEnumTypeName(const EnumType& t, const char* const (&typeValues )[10])
{
std::string s(typeValues[static_cast<int>(t)]);
return (s.size()) ? s.substr(s.find_last_of(":") + 1) : "";
}
};
我还添加了constexpr
,并通过const
引用传递值,因为你不想改变它。
我的建议是使用std::array
,它减轻了传递数组的所有问题。
std::array
溶液
#include <iostream>
#include <string>
#include <algorithm>
#include <array>
#define stringify(name) #name
struct MyClass
{
enum class TYPE
{
UNKNOWN = 0,
CLIENT,
SERVER
};
MyClass(TYPE t)
:_type(t)
{
}
TYPE type()
{
return _type;
}
constexpr static auto typeValue = std::array{
stringify(TYPE::UNKNOWN),
stringify(TYPE::CLIENT),
stringify(TYPE::SERVER)
};
private:
TYPE _type;
};
struct EnumStringify
{
template <class EnumType, class Array>
static std::string getEnumTypeName(const EnumType& t, const Array& array)
{
std::string s(array[static_cast<int>(t)]);
return (s.size()) ? s.substr(s.find_last_of(":") + 1) : "";
}
};
int main()
{
MyClass a(MyClass::TYPE::CLIENT);
std::cout << EnumStringify::getEnumTypeName(a.type(), MyClass::typeValue).c_str();
}
模板变量如果我要编写这样的代码,我会使用模板变量,用户可以专门为他们自己的枚举提供字符串:
//
// "Stringify Library"
#define stringify(name) #name
struct MissingEnumTable{};
template<class Enum>
constexpr MissingEnumTable stringified_enum{};
template <class E>
static std::string getEnumTypeName(const E& t)
{
static_assert(!std::is_same_v<decltype(stringified_enum<E>),MissingEnumTable>,
"Enum E is missing stringified_enum table specialization.");
std::string s(stringified_enum<E>[static_cast<int>(t)]);
return (s.size()) ? s.substr(s.find_last_of(":") + 1) : "";
}
// END
// Library user
// - Provide strings for a custom array
enum class TYPE
{
UNKNOWN = 0,
CLIENT,
SERVER
};
template<>
constexpr auto stringified_enum<TYPE> = std::array{
stringify(TYPE::UNKNOWN),
stringify(TYPE::CLIENT),
stringify(TYPE::SERVER)
};
int main()
{
std::cout << getEnumTypeName(TYPE::UNKNOWN).c_str();
}