以下是一些枚举类:
enum class Race : char {AINU, ELF, DWARF, MAN, EAGLE, HOBBIT, ENT, ORC, WIZARD};
enum class Color: char {RED, ORANGE, YELLOW, GREEN, BLUE, PURPLE};
enum class Direction: char{UP, DOWN, LEFT, RIGHT};
我想为每个实现 enum_to_string函数和 string_to_enum函数。
将枚举转换为字符串没有问题,因为我可以重载相同的函数名称。
std::string to_string(Race const& enum_value);
std::string to_string(Color const& enum_value);
std::string to_string(Direction const& enum_value);
但是,转换为枚举时,不能以相同的方式重载,因为只有返回类型才会不同。 (我也不想,因为不同的枚举可以用相同的字符串表示。)
将字符串转换为枚举是否可以采用以下方法之一?
Race race = to_enum<Race>("elf");
Color color = to_enum<Color>("green");
std::string blah{"up"};
Direction dir{to_enum<Direction>(blah)};
或可能:
Race race = to_enum(Race,"elf");
Color color = to_enum(Color,"green");
std::string blah{"up"};
Direction dir{to_enum(Direction,blah)};
C ++能否支持这些行为中的一种或两种?
我正在尝试避免使用不同的函数名称:
Race to_race(std::string const& str);
Color to_color(std::string const& str);
Direction to_direction(std::string const& str);
这是我能提出的最接近的事情,
template <typename T>struct to_enum{};
template <>
struct to_enum<Color>{
static Color convert(std::string const& str){
//match the string with a color enum, and return that color enum
//(or like a default color enum if the string is garbage or something)
}
};
然后你这样称呼它:
Color color = to_enum<Color>::convert("red");
我们可以摆脱转换吗?或者可能实施这个?
Color color = to_enum(Color,"red");
答案 0 :(得分:7)
使用功能模板和专业化。这些是罕见的情况,我认为功能专业化确实有帮助。
template<typename TEnum>
TEnum enum_cast(std::string const & s);
然后为每个枚举类型专门化它。我更改了名称,因此您可以像演员一样阅读:
Color color = enum_cast<Color>("blue");
或parse
也是一个好名字。选择你认为好的任何东西。我个人会选择parse
或enum_cast
。
现在to_string
,您可以定义重载(您已经拥有):
std::string to_string(Color c);
std::string to_string(Race r);
std::string to_string(Direction d);
请勿对to_string
使用模板和专精。超载确实很好。
答案 1 :(得分:4)
然后你这样称呼它:
Color color = to_enum<Color>::convert("red");
我们可以摆脱转换吗?
当然可以!只需封装电话:
template <typename Enum>
Enum to_enum(std::string const& from) {
return to_enum_helper<Enum>::convert(from);
}
其中to_enum_helper
是您之前定义的结构。 (编辑:或者你直接专门化这个功能,如Nawaz的回答所示。)
或者,如果那是你的一杯茶,你可以使用重载而不是专业化:
Race to_enum_helper(std::string const& from, Race) {
// Implement for enum class Race
}
Color to_enum_helper(std::string const& from, Color) {
// Implement for enum class Color
}
template <typename Enum>
Enum to_enum(std::string const& from) {
return to_enum_helper(from, Enum());
}
这里,to_enum_helper
的第二个参数仅用于区分不同的重载。
答案 2 :(得分:1)
但是,在转换为枚举时,不能以相同的方式重载,因为只有返回类型会有所不同。
您可以重载转换运算符以编写仅因返回类型而不同的重载函数:
#include <string>
#include <iostream>
enum Race {};
enum Color {};
struct to_one_of_them {
operator Race () const { std::cout << "to Race()\n"; return Race(); }
operator Color () const { std::cout << "to Color()\n"; return Color(); }
to_one_of_them() = delete;
private:
std::string str;
to_one_of_them(std::string const &str) : str(str) {}
friend to_one_of_them to_enum(std::string const&);
};
to_one_of_them to_enum(std::string const &str) {
return {str};
}
int main () {
Race r = to_enum("meh");
Color c = to_enum("meh");
}
然而,这种技术几乎未被使用,因此不是C ++习语,因此可能不值得学习。