【问题标题】:c++ conversion of strongly typed enumsc++ 强类型枚举的转换
【发布时间】:2017-02-01 04:35:08
【问题描述】:

使用强类型枚举代替枚举有一些很好的论据。然而,除了不必要的风险之外,到 int 的可转换性还提供了一些不错的用例。就我而言,主要是将其放入字符串流中进行记录和比较。

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 ) {
        ... 
    }
}

我确实怀念旧枚举的这些功能,而且我可能不是唯一一个。有什么好的方法可以使用强类型枚举并且仍然可以轻松地记录和比较它们?

【问题讨论】:

  • 我对其进行了编辑以表示我使用枚举的实际示例
  • 对不起,我不记得强类型枚举是什么。

标签: c++


【解决方案1】:

你可以使用std::underlying_type:

void logStuff( RiskLevel rl ) {
    typedef std::underlying_type<RiskLevel>::type int_type;
    stringstream ss;
    ss << int_type(rl);
    Logger(ss);
}

【讨论】:

    【解决方案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 ) {
            ... 
        }
    }
    

    this answer 更深入。

    【讨论】:

      【解决方案3】:

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

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

      然后您可以让流插入操作符实际记录,例如,枚举器的名称。

      【讨论】:

      • 这看起来很简洁,但是为每个枚举定义它会很冗长。只是出于好奇,是否可以只为所有作用域枚举编写模板?
      • 是的;你可以使用std::enable_ifstd::is_enum。 (如果您希望它用于强类型枚举,而不是常规枚举,请参阅this question。)
      【解决方案4】:

      也许可以利用 c++11 的枚举类。您可以明确指定您希望枚举的类型。

      enum class Boo : char {
          START = 'S',
          END = 'E'
      };
      
      enum class Foo :  unsigned int {
          TOP = 1,
          BOTTOM = 2
      };
      

      【讨论】:

      • 我尝试使用 enum class RiskLvl : int { NONE = 0, .. } 但这给了我错误:无法将 std::basic_ostream 左值绑定到 std::basic_ostream&&
      • 流式使用时,需要手动static_cast&lt;int&gt;。如果你想避免这样的演员,上面使用 std::underlying_type 的答案是最好的(它适用于枚举类)。
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2012-09-16
      • 2023-02-21
      • 1970-01-01
      • 2021-07-23
      • 2017-10-14
      • 2011-03-03
      • 1970-01-01
      相关资源
      最近更新 更多