我可以根据类型ID实现其签名只有不同的模板化函数吗?

时间:2013-01-14 15:21:52

标签: c++ class function c++11 enums

以下是一些枚举类:

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");

3 个答案:

答案 0 :(得分:7)

使用功能模板和专业化。这些是罕见的情况,我认为功能专业化确实有帮助。

template<typename TEnum>
TEnum enum_cast(std::string const & s);
然后

为每个枚举类型专门化它。我更改了名称,因此您可以像演员一样阅读:

Color color = enum_cast<Color>("blue");

parse也是一个好名字。选择你认为好的任何东西。我个人会选择parseenum_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 ++习语,因此可能不值得学习。