【发布时间】:2019-04-01 05:11:27
【问题描述】:
我正在尝试将编译时间字符串与枚举值相关联。
这是我第一次尝试解决这个问题:
EnumValue 将在字符串和枚举之间进行编译时关联
template<typename EnumType, int EnumIntValue, const char* EnumStrValue>
class EnumValue
{
public:
static const char* toString()
{
return EnumStrValue;
}
static const int toInt()
{
return EnumIntValue;
}
static EnumType get()
{
return static_cast<EnumType>(EnumIntValue);
}
};
EnumValueHolder 将保存字符串和枚举的实际值。 我不喜欢我当前的设计,因为它仍然需要保存一个指向字符串的指针。我更愿意为此使用编译时关联,但未能提出更优雅的解决方案
template<typename EnumType>
class EnumValueHolder
{
public:
EnumValueHolder()
{}
EnumValueHolder(const EnumType& value, const char* str)
: value(value), str(str)
{}
bool operator==(const EnumValueHolder<EnumType>& rhs) { return value == rhs.value; }
bool operator==(const EnumType& rhs)const { return value == rhs; }
operator EnumType()const
{
return value;
}
const char* toString()const
{
return str;
}
const int toInt()const
{
return static_cast<int>(value);
}
private:
EnumType value;
char const* str;
};
Marcos 可以轻松引用枚举类型和枚举值持有者构造
#define ENUM_VALUE_TYPE(enumName, enumValue) \
EnumValue<enumName, (int)enumName::enumValue, str_##enumValue>
#define ENUM_VALUE_MAKE(enumName, enumValue) \
EnumValueHolder<enumName> { \
ENUM_VALUE_TYPE(enumName, enumValue)::get(), \
ENUM_VALUE_TYPE(enumName, enumValue)::toString() }
以下是我的测试用例和使用示例:
const char str_Apple[] = "Apple";
const char str_Orange[] = "Orange";
const char str_Pineapple[] = "Pineapple";
enum class EFruits
{
Apple,
Orange,
Pineapple
};
int main()
{
auto evApple = ENUM_VALUE_MAKE(EFruits, Apple);
std::cout << evApple.toString() << std::endl;
auto evOrange = ENUM_VALUE_MAKE(EFruits, Orange);
std::cout << evOrange.toString() << std::endl;
std::cout << "compare: " << (evApple == evOrange) << std::endl;
evApple = evOrange;
std::cout << evApple.toString() << std::endl;
auto myfruit = ENUM_VALUE_MAKE(EFruits, Pineapple);
std::cout << myfruit.toString() << std::endl;
switch (myfruit)
{
case EFruits::Apple:
std::cout << "Im an apple!" << std::endl;
break;
case EFruits::Orange:
std::cout << "Im an Orange!" << std::endl;
break;
case EFruits::Pineapple:
std::cout << "Im a Pineapple!" << std::endl;
break;
default:break;
}
}
其中一个目标是删除全局字符串:
const char str_Apple[] = "Apple";
const char str_Orange[] = "Orange";
const char str_Pineapple[] = "Pineapple";
另一种是创建一个将枚举与字符串关联的宏
//Some crazy define that makes pairs of enum values and strings as
//compile time constants
#define DEFINE_ENUM_STRING(enumValue)\
enumValue, #enumValue
//Ideally, the macro would be used like this. This should be usable in any
//scope (global, namespace, class)
//with any access specifier (private, protected, public)
enum class EFruits
{
DEFINE_ENUM_STRING(Apple),
DEFINE_ENUM_STRING(Orange),
DEFINE_ENUM_STRING(Pineapple)
};
所以有两个主要问题:
1) 这种当前的设计真的能保证将枚举与字符串关联起来的编译时间常数吗?
2) 如何定义一个宏来对枚举值进行字符串化并使用 1 行在枚举类中声明该值?
编辑:这应该可以在使用 c++ 11 的 win64 平台上与 msvs2017 一起工作和编译。
谢谢。
【问题讨论】:
标签: c++ templates enums compile-time-constant