首页 文章

如何在C 11中输出枚举类的值

提问于
浏览
71

如何在C 11中输出 enum class 的值?在C 03中,它是这样的:

#include <iostream>

using namespace std;

enum A {
  a = 1,
  b = 69,
  c= 666
};

int main () {
  A a = A::c;
  cout << a << endl;
}

在c 0x中,此代码无法编译

#include <iostream>

using namespace std;

enum class A {
  a = 1,
  b = 69,
  c= 666
};

int main () {
  A a = A::c;
  cout << a << endl;
}


prog.cpp:13:11: error: cannot bind 'std::ostream' lvalue to 'std::basic_ostream<char>&&'
/usr/lib/gcc/i686-pc-linux-gnu/4.5.1/../../../../include/c++/4.5.1/ostream:579:5: error:   initializing argument 1 of 'std::basic_ostream<_CharT, _Traits>& std::operator<<(std::basic_ostream<_CharT, _Traits>&&, const _Tp&) [with _CharT = char, _Traits = std::char_traits<char>, _Tp = A]'

编译在Ideone.com

5 回答

  • 15

    与未作用域的枚举不同,作用域枚举不可隐式转换为其整数值 . 您需要使用强制转换将其显式转换为整数:

    std::cout << static_cast<std::underlying_type<A>::type>(a) << std::endl;
    

    您可能希望将逻辑封装到函数模板中:

    template <typename Enumeration>
    auto as_integer(Enumeration const value)
        -> typename std::underlying_type<Enumeration>::type
    {
        return static_cast<typename std::underlying_type<Enumeration>::type>(value);
    }
    

    用作:

    std::cout << as_integer(a) << std::endl;
    
  • 9
    #include <iostream>
    #include <type_traits>
    
    using namespace std;
    
    enum class A {
      a = 1,
      b = 69,
      c= 666
    };
    
    std::ostream& operator << (std::ostream& os, const A& obj)
    {
       os << static_cast<std::underlying_type<A>::type>(obj);
       return os;
    }
    
    int main () {
      A a = A::c;
      cout << a << endl;
    }
    
  • 1

    可以使用与unscoped枚举相同的语法来获取第二个示例(即使用范围枚举的示例) . 此外,该解决方案是通用的,适用于所有作用域枚举,而不是为每个作用域枚举编写代码(如@ForEveR提供的answer所示) .

    解决方案是编写一个通用 operator<< 函数,该函数适用于任何作用域枚举 . 该解决方案采用SFINAE来自std::enable_if,如下所示 .

    #include <iostream>
    #include <type_traits>
    
    // Scoped enum
    enum class Color
    {
        Red,
        Green,
        Blue
    };
    
    // Unscoped enum
    enum Orientation
    {
        Horizontal,
        Vertical
    };
    
    // Another scoped enum
    enum class ExecStatus
    {
        Idle,
        Started,
        Running
    };
    
    template<typename T>
    std::ostream& operator<<(typename std::enable_if<std::is_enum<T>::value, std::ostream>::type& stream, const T& e)
    {
        return stream << static_cast<typename std::underlying_type<T>::type>(e);
    }
    
    int main()
    {
        std::cout << Color::Blue << "\n";
        std::cout << Vertical << "\n";
        std::cout << ExecStatus::Running << "\n";
        return 0;
    }
    
  • 32

    (我不允许发表评论 . )我建议对James McNellis已经很好的答案进行以下改进:

    template <typename Enumeration>
    constexpr auto as_integer(Enumeration const value)
        -> typename std::underlying_type<Enumeration>::type
    {
        static_assert(std::is_enum<Enumeration>::value, "parameter is not of type enum or enum class");
        return static_cast<typename std::underlying_type<Enumeration>::type>(value);
    }
    

    • constexpr :允许我使用枚举成员值作为编译时数组大小

    • static_assert is_enum :到'ensure'编译时该函数做了某事 . 仅提供枚举,如建议的那样

    顺便说一句,我问自己:为什么我想在我的枚举成员中分配数字值时使用 enum class ?考虑转换努力 .

    也许我会像我在这里建议的那样回到普通的 enumHow to use enums as flags in C++?


    根据@TobySpeight的建议,没有static_assert的另一种(更好)的味道:

    template <typename Enumeration>
    constexpr std::enable_if_t<std::is_enum<Enumeration>::value,
    std::underlying_type_t<Enumeration>> as_number(const Enumeration value)
    {
        return static_cast<std::underlying_type_t<Enumeration>>(value);
    }
    
  • 91

    写得更简单,

    enum class Color
    {
        Red = 1,
        Green = 11,
        Blue = 111
    };
    
    int value = static_cast<int>(Color::Blue); // 111
    

相关问题