C++强类型枚举的转换

3
使用强类型枚举而不是枚举有一些好的理由。但是,强类型枚举可以转换为int类型,除了它带来的风险外,还有一些很好的用例。在我的情况下,主要是将其放入stringstream中进行日志记录和比较。
enum RiskLevel { None, Warn, Low, High, Critical };

void logStuff( RiskLevel rl ) {
    stringstream ss;
    ss << rl;
    LOG(s);
}

void compareEnum( RiskLevel rl ) {
    if ( rl > RiskLevel::Low ) {
        ... 
    }
}

我很想念旧版枚举类型的这些特性,而且我可能不是唯一一个这样想的人。有什么好方法可以使用强类型枚举并且仍然容易记录和比较它们吗?


我编辑了一个实际的例子,用枚举来表示 - chrise
抱歉,我不记得强类型枚举是什么了。 - Justin
4个回答

4
您可以使用std::underlying_type
void logStuff( RiskLevel rl ) {
    typedef std::underlying_type<RiskLevel>::type int_type;
    stringstream ss;
    ss << int_type(rl);
    Logger(ss);
}

2

您可以(另外)实现自己的日志记录和比较重载,这样可以为您提供更多的灵活性:

std::ostream& operator<<(ostream& os, RiskLevel rl) {
    os << std::underlying_type<RiskLevel>::type(rl);
    return os;
}

bool operator<(RiskLevel rl1, RiskLevel rl2) {
    return std::underlying_type<RiskLevel>::type(rl1) <
               std::underlying_type<RiskLevel>::type(rl2);
}

那么您可以让流插入运算符实际记录枚举器的名称。


听起来很不错,但为每个枚举定义这个会很啰嗦。只是出于好奇,是否有可能为所有作用域枚举编写模板? - chrise
1
是的,您可以使用 std::enable_ifstd::is_enum。 (如果您只想用于强类型枚举,而不是常规枚举,请参见此问题。) - qxz

2

定义一元运算符+,将其用于执行到整数类型的转换。

enum RiskLevel { None, Warn, Low, High, Critical };

auto operator + ( RiskLevel value )
    { return std::underlying_type_t< RiskLevel >( value ); }

void logStuff( RiskLevel rl ) {
    stringstream ss;
    ss << + rl;
    LOG(s);
}

void compareEnum( RiskLevel rl ) {
    if ( + rl > + RiskLevel::Low ) {
        ... 
    }
}

这个回答更深入地解释了相关的IT技术。


2

也许可以利用C++11的枚举类(enum class)。您可以明确指定枚举类型。

enum class Boo : char {
    START = 'S',
    END = 'E'
};

enum class Foo :  unsigned int {
    TOP = 1,
    BOTTOM = 2
};

我尝试使用枚举类RiskLvl : int { NONE = 0, .. },但这给了我一个错误:无法将std::basic_ostream<char> lvalue绑定到std::basic_ostream<char>&&。 - chrise
1
当与Stream一起使用时,您确实需要手动使用static_cast<int>。如果要避免这样的转换,上面使用std :: underlying_type的答案是最好的(它适用于枚举类)。 - greedy52

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接