Есть ли простой способ конвертировать перечисление C ++ в строку? - PullRequest
113 голосов
/ 14 октября 2008

Предположим, у нас есть некоторые именованные перечисления:

enum MyEnum {
      FOO,
      BAR = 0x50
};

То, что я нашел в Google, - это скрипт (любой язык), который сканирует все заголовки в моем проекте и генерирует заголовок с одной функцией на каждое перечисление.

char* enum_to_string(MyEnum t);

И реализация с чем-то вроде этого:

char* enum_to_string(MyEnum t){
      switch(t){
         case FOO:
            return "FOO";
         case BAR:
            return "BAR";
         default:
            return "INVALID ENUM";
      }
 }

Гоча действительно с перечислениями typedefed и безымянными перечислениями в стиле C. Кто-нибудь знает что-нибудь для этого?

РЕДАКТИРОВАТЬ: Решение не должно изменять мой источник, за исключением сгенерированных функций. Перечисления в API, поэтому использование решений, предложенных до сих пор, просто не вариант.

Ответы [ 35 ]

0 голосов
/ 07 марта 2014

Вот попытка автоматически получить операторы << и >> в enum с помощью однострочной макрокоманды ...

Определения:

#include <string>
#include <iostream>
#include <stdexcept>
#include <algorithm>
#include <iterator>
#include <sstream>
#include <vector>

#define MAKE_STRING(str, ...) #str, MAKE_STRING1_(__VA_ARGS__)
#define MAKE_STRING1_(str, ...) #str, MAKE_STRING2_(__VA_ARGS__)
#define MAKE_STRING2_(str, ...) #str, MAKE_STRING3_(__VA_ARGS__)
#define MAKE_STRING3_(str, ...) #str, MAKE_STRING4_(__VA_ARGS__)
#define MAKE_STRING4_(str, ...) #str, MAKE_STRING5_(__VA_ARGS__)
#define MAKE_STRING5_(str, ...) #str, MAKE_STRING6_(__VA_ARGS__)
#define MAKE_STRING6_(str, ...) #str, MAKE_STRING7_(__VA_ARGS__)
#define MAKE_STRING7_(str, ...) #str, MAKE_STRING8_(__VA_ARGS__)
#define MAKE_STRING8_(str, ...) #str, MAKE_STRING9_(__VA_ARGS__)
#define MAKE_STRING9_(str, ...) #str, MAKE_STRING10_(__VA_ARGS__)
#define MAKE_STRING10_(str) #str

#define MAKE_ENUM(name, ...) MAKE_ENUM_(, name, __VA_ARGS__)
#define MAKE_CLASS_ENUM(name, ...) MAKE_ENUM_(friend, name, __VA_ARGS__)

#define MAKE_ENUM_(attribute, name, ...) name { __VA_ARGS__ }; \
    attribute std::istream& operator>>(std::istream& is, name& e) { \
        const char* name##Str[] = { MAKE_STRING(__VA_ARGS__) }; \
        std::string str; \
        std::istream& r = is >> str; \
        const size_t len = sizeof(name##Str)/sizeof(name##Str[0]); \
        const std::vector<std::string> enumStr(name##Str, name##Str + len); \
        const std::vector<std::string>::const_iterator it = std::find(enumStr.begin(), enumStr.end(), str); \
        if (it != enumStr.end())\
            e = name(it - enumStr.begin()); \
        else \
            throw std::runtime_error("Value \"" + str + "\" is not part of enum "#name); \
        return r; \
    }; \
    attribute std::ostream& operator<<(std::ostream& os, const name& e) { \
        const char* name##Str[] = { MAKE_STRING(__VA_ARGS__) }; \
        return (os << name##Str[e]); \
    }

Использование:

// Declare global enum
enum MAKE_ENUM(Test3, Item13, Item23, Item33, Itdsdgem43);

class Essai {
public:
    // Declare enum inside class
    enum MAKE_CLASS_ENUM(Test, Item1, Item2, Item3, Itdsdgem4);

};

int main() {
    std::cout << Essai::Item1 << std::endl;

    Essai::Test ddd = Essai::Item1;
    std::cout << ddd << std::endl;

    std::istringstream strm("Item2");
    strm >> ddd;

    std::cout << (int) ddd << std::endl;
    std::cout << ddd << std::endl;
}

Не уверен насчет ограничений этой схемы, хотя ... комментарии приветствуются!

0 голосов
/ 08 июня 2010

Вот программа CLI, которую я написал, чтобы легко преобразовывать перечисления в строки. Он прост в использовании и для его выполнения требуется около 5 секунд (включая время, когда cd перейдет в каталог, содержащий программу, затем запустит ее, передав ей файл, содержащий перечисление).

Скачать здесь: http://www.mediafire.com/?nttignoozzz

Тема обсуждения по ней здесь: http://cboard.cprogramming.com/projects-job-recruitment/127488-free-program-im-sharing-convertenumtostrings.html

Запустите программу с аргументом "--help", чтобы получить описание, как ее использовать.

0 голосов
/ 15 апреля 2013

Как вариант, используйте простой lib> http://codeproject.com/Articles/42035/Enum-to-String-and-Vice-Versa-in-C

В коде

#include <EnumString.h>

enum FORM {
    F_NONE = 0,
    F_BOX,
    F_CUBE,
    F_SPHERE,
};

добавить строки

Begin_Enum_String( FORM )
{
    Enum_String( F_NONE );
    Enum_String( F_BOX );
    Enum_String( F_CUBE );
    Enum_String( F_SPHERE );
}
End_Enum_String;

Работает нормально, , если значения в перечислении не повторяются .

Пример использования

enum FORM f = ...
const std::string& str = EnumString< FORM >::From( f );

и наоборот

assert( EnumString< FORM >::To( f, str ) );
0 голосов
/ 03 февраля 2019

Этот вопрос является дубликатом,

Однако ни на один из вопросов я не нашел хороших ответов.

Изучив эту тему, я нашел два замечательных решения с открытым исходным кодом:

wise_enum

  • Автономная библиотека smart enum для C ++ 11/14/17 . Он поддерживает все стандартные функциональные возможности, которые вы ожидаете от класса smart enum в C ++.
  • Ограничения: требуется минимум C ++ 11.

Лучше Enums

  • Отражающая библиотека перечислений времени компиляции с чистым синтаксисом , в одном заголовочном файле и без зависимостей.
  • Ограничения: основаны на макросах, не могут использоваться внутри класса.

Примечание: я повторяю эту рекомендацию здесь. Этот вопрос имеет много трафика / просмотров и действительно требует перечисления решений выше.

0 голосов
/ 14 октября 2008

Это практически единственный способ сделать это (массив строк также может работать).

Проблема в том, что после компиляции программы на C двоичное значение перечисления - это все, что используется, и имя исчезает.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...