web-dev-qa-db-ja.com

値から列挙項目名を取得する方法

これとして列挙型を宣言しましたが、

_enum WeekEnum
{
Mon = 0;
Tue = 1;
Wed = 2;
Thu = 3;
Fri = 4;
Sat = 5;
Sun = 6;
};
_

アイテムの値が「0、1など」の場合、「Mon、Tueなど」というアイテム名を取得するにはどうすればよいですか。

私はすでにこの機能を持っています

Log(Today is "2", enjoy! );

そして今、私は以下の出力が欲しい

今日は水です

30
Nano HE

C++のenumは、Java enums。

通常のアプローチは、std::map<WeekEnum,std::string>

std::map<WeekEnum,std::string> m;
m[Mon] = "Monday";
//...
m[Sun] = "Sunday";
26
Luchian Grigore

いいえ、コンパイル時にすべてのシンボルが破棄されるため、C++の値から「名前」を取得する方法はありません。

この方法が必要な場合があります Xマクロ

9
RolandXu

列挙は逆配列のようなものです。あなたが欲しいと思うのはこれです:

const char * Week[] = { "", "Sunday", "Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday" };  // The blank string at the beginning is so that Sunday is 1 instead of 0.
cout << "Today is " << Week[2] << ", enjoy!";  // Or whatever you'de like to do with it.
8
Cosine

出力を実行する演算子を定義できます。

std::ostream& operator<<(std::ostream& lhs, WeekEnum e) {
    switch(e) {
    case Monday: lhs << "Monday"; break;
    .. etc
    }
    return lhs;
}
6
Puppy

Xマクロを使用してenumを定義するもう1つの巧妙なトリックを次に示します。

#include <iostream>

#define WEEK_DAYS \
X(MON, "Monday", true) \
X(TUE, "Tuesday", true) \
X(WED, "Wednesday", true) \
X(THU, "Thursday", true) \
X(FRI, "Friday", true) \
X(SAT, "Saturday", false) \
X(Sun, "Sunday", false)

#define X(day, name, workday) day,
enum WeekDay : size_t
{
    WEEK_DAYS
};
#undef X

#define X(day, name, workday) name,
char const *weekday_name[] =
{
    WEEK_DAYS
};
#undef X

#define X(day, name, workday) workday,
bool weekday_workday[]
{
    WEEK_DAYS
};
#undef X

int main()
{
    std::cout << "Enum value: " << WeekDay::THU << std::endl;
    std::cout << "Name string: " << weekday_name[WeekDay::THU] << std::endl;
    std::cout << std::boolalpha << "Work day: " << weekday_workday[WeekDay::THU] << std::endl;

    WeekDay wd = Sun;
    std::cout << "Enum value: " << wd << std::endl;
    std::cout << "Name string: " << weekday_name[wd] << std::endl;
    std::cout << std::boolalpha << "Work day: " << weekday_workday[wd] << std::endl;

    return 0;
}

ライブデモ: https://ideone.com/bPAVTM

出力:

Enum value: 3
Name string: Thursday
Work day: true
Enum value: 6
Name string: Sunday
Work day: false
4
Killzone Kid

アイテムの値が「0、1など」の場合、アイテム名「Mon、Tueなど」を取得するにはどうすればよいですか。

古いCコード(かなり前)で、次のようなコードが見つかりました。

std::string weekEnumToStr(int n)
{
   std::string s("unknown");
   switch (n)
   {
   case 0: { s = "Mon"; } break;
   case 1: { s = "Tue"; } break;
   case 2: { s = "Wed"; } break;
   case 3: { s = "Thu"; } break;
   case 4: { s = "Fri"; } break;
   case 5: { s = "Sat"; } break;
   case 6: { s = "Sun"; } break;
   }
   return s;
}

欠点:これは、列挙値と関数の間に「病理学的依存関係」を確立します...つまり、列挙を変更する場合は、一致するように関数を変更する必要があります。これはstd :: mapであっても当てはまると思います。

列挙コードから関数コードを生成するユーティリティを見つけたことを漠然と覚えています。列挙テーブルの長さは数百に拡大しました...そしてある時点で、コードを書くためにコードを書くことはおそらく適切な選択です。


注意 -

組み込みシステムの強化の取り組みで、私のチームは、enum int値をテキスト文字列にマッピングするために使用されるヌル終了文字列の多くのテーブル(100+?)を置き換えました。

テーブルの問題は、これらのテーブルの多くがコード/メモリの1つの領域に収集されたため、範囲外の値がしばしば気付かれないことでした。後続のテーブルからヌル終了文字列を返しました。

Function-with-switchステートメントを使用すると、スイッチのデフォルト句にアサートを追加することもできます。アサーションはテスト中にさらにいくつかのコーディングエラーを発見し、私たちのアサーションはフィールドテクノロジーが検索できるstatic-ram-system-logに結び付けられました。

1
2785528

実際の列挙ラベルが値に関連付けられていることがわかっている場合は、コンテナとC++ 17のstd::string_viewを使用して、追跡中に[]演算子で値とその文字列表現にすばやくアクセスできますあなた自身。 std::string_viewは、作成時にのみメモリを割り当てます。パフォーマンスをさらに節約するために、実行時に使用可能にする場合は、static constexprで指定することもできます。この小さなコンソールアプリはかなり高速です。

#include <iostream>
#include <string_view>
#include <Tuple>    
int main() {
    enum class Weekdays { //default behavior starts at 0 and iterates by 1 per entry
        Monday,Tuesday,Wednesday,Thursday,Friday,Saturday,Sunday
    };

    static constexpr std::string_view Monday    = "Monday";
    static constexpr std::string_view Tuesday   = "Tuesday";
    static constexpr std::string_view Wednesday = "Wednesday";
    static constexpr std::string_view Thursday  = "Thursday";
    static constexpr std::string_view Friday    = "Friday";
    static constexpr std::string_view Saturday  = "Saturday";
    static constexpr std::string_view Sunday    = "Sunday";
    static constexpr std::string_view opener    = "enum[";
    static constexpr std::string_view closer    = "] is ";
    static constexpr std::string_view semi      = ":";

    std::pair<Weekdays, std::string_view> Weekdays_List[] = {
        std::make_pair(Weekdays::Monday,    Monday),
        std::make_pair(Weekdays::Tuesday,   Tuesday),
        std::make_pair(Weekdays::Wednesday, Wednesday),
        std::make_pair(Weekdays::Thursday,  Thursday),
        std::make_pair(Weekdays::Friday,    Friday),
        std::make_pair(Weekdays::Saturday,  Saturday),
        std::make_pair(Weekdays::Sunday,    Sunday)
    };

    for (int i=0;i<sizeof(Weekdays_List)/sizeof(Weekdays_List[0]);i++) {
        std::cout<<opener<<i<<closer<<Weekdays_List[(int)i].second<<semi\
        <<(int)Weekdays_List[(int)i].first<<std::endl;
    }    
    return 0;
}

出力:

enum[0] is Monday:0
enum[1] is Tuesday:1
enum[2] is Wednesday:2
enum[3] is Thursday:3
enum[4] is Friday:4
enum[5] is Saturday:5
enum[6] is Sunday:6
0

@RolandXuが指すXマクロに似た手法で、私は素晴らしい成功を収めました。文字列化演算子も多用しました。この手法は、アイテムが文字列と数値トークンの両方として表示されるアプリケーションドメインがある場合、メンテナンスの悪夢を軽減します。

マクロX(...)行を自動生成できるように、機械可読ドキュメントが利用できる場合に特に便利です。新しいドキュメントは、すぐに一貫性のあるプログラム更新をもたらします。文字列、列挙型、およびそれらの間で両方向に翻訳される辞書(PCL6トークンを扱っていました)。

プリプロセッサのコードはかなりいように見えますが、これらの技術はすべてヘッダーファイルに隠されているため、再度触れる必要はなく、ソースファイルも同様です。すべてがタイプセーフです。変更される唯一のものは、すべてのX(...)行を含むテキストファイルです。これはおそらく自動生成されます。

0