123

enum classC++11で an の値を出力するにはどうすればよいですか? 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で編集

4

8 に答える 8

44
#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;
}
于 2012-07-10T20:33:41.400 に答える
24

2 番目の例 (つまり、スコープ付き列挙型を使用するもの) を、スコープなし列挙型と同じ構文を使用して動作させることができます。さらに、ソリューションは汎用的であり、すべてのスコープ付き列挙型に対して機能し、スコープ付き列挙型ごとにコードを記述します ( @ForEveRが提供する回答に示されているように)。

operator<<解決策は、スコープ付き列挙型に対して機能する汎用関数を作成することです。ソリューションはSFINAE viastd::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;
}
于 2015-01-29T04:02:12.413 に答える
10

(まだコメントすることはできません。) 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: 関数が sth を実行することをコンパイル時に「保証」します。提案されているように、列挙のみを使用

ところで、私は自問自答しています: enum classenum メンバーに数値を割り当てたいときに、なぜこれを使用する必要があるのでしょうか?! 変換作業を考慮します。

enumおそらく、ここで提案したように、通常に戻るでしょう: How 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);
}
于 2014-11-07T19:57:27.737 に答える
1

C ++ 23以降、

std::to_underlying他のすべての回答と同じことを行いますが、それは標準です

于 2021-10-22T08:10:15.637 に答える
0

次のようなことができます。

//outside of main
namespace A
{
    enum A
    {
        a = 0,
        b = 69,
        c = 666
    };
};

//in main:

A::A a = A::c;
std::cout << a << std::endl;
于 2019-10-02T16:37:46.443 に答える