Предположим, у нас есть несколько именованных перечислений:
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";
}
}
Проблема действительно связана с перечислениями с определением типа и безымянными перечислениями в стиле C. Кто-нибудь знает что-нибудь по этому поводу?
РЕДАКТИРОВАТЬ: решение не должно изменять мой источник, за исключением сгенерированных функций. Перечисления находятся в API, поэтому использование предложенных до сих пор решений просто не вариант.
Ответы:
Вы можете попробовать GCCXML .
Запуск GCCXML в вашем примере кода дает:
Вы можете использовать любой язык, который предпочитаете, чтобы извлечь теги Enumeration и EnumValue и сгенерировать желаемый код.
источник
X-макросы - лучшее решение. Пример:
colours.def:
Однако я обычно предпочитаю следующий метод, чтобы можно было немного изменить строку.
источник
#define X(a, b) #b
. Это необходимо только в том случае, если определение выглядит такX(Red, red)
, а не определение, показанное в ответе,X(Red, "red")
@hydroo: Без лишнего файла:
источник
MetaSyntacticVariableNames[]
частью объявления класса, создав методstatic const char* getNameByEnum(MetaSyntacticVariable e) { /*code to return the static string*/ }
Я стараюсь создать массив C с именами в том же порядке и позиции, что и значения перечисления.
например.
тогда вы можете использовать массив в тех местах, где вам нужно удобочитаемое значение, например
Вы можете немного поэкспериментировать с оператором преобразования строк (см. # В справочнике по препроцессору), который при некоторых обстоятельствах будет делать то, что вы хотите, например:
напечатает "красный" в стандартный вывод. К сожалению, это не сработает для переменной (так как вы получите распечатанное имя переменной)
источник
У меня есть невероятно простой в использовании макрос, который делает это совершенно СУХИМ способом. Он включает в себя вариативные макросы и некоторую простую магию синтаксического анализа. Поехали:
Чтобы использовать это в своем коде, просто выполните:
источник
QT может использовать это (благодаря компилятору метаобъектов):
Источник
источник
Это можно сделать в C ++ 11
источник
Я только что заново изобрел это колесо сегодня и подумал, что поделюсь им.
Эта реализация не требует каких-либо изменений в коде, определяющем константы, которые могут быть перечислениями или
#define
s, или чем-либо еще, переходящим в целое число - в моем случае у меня были символы, определенные в терминах других символов. Он также хорошо работает с разреженными значениями. Он даже позволяет использовать несколько имен для одного и того же значения, всегда возвращая первое. Единственным недостатком является то, что вам нужно создать таблицу констант, которая может устареть, например, при добавлении новых.Пример того, как вы бы это использовали:
IdToName
Функция зависит отstd::lower_bound
делать быстрый поиск, что требует таблицы для сортировки. Если первые две записи в таблице не в порядке, функция отсортирует их автоматически.Изменить: комментарий заставил меня подумать о другом способе использования того же принципа. Макрос упрощает создание большого
switch
заявления.источник
switch and case
потому что это просто и понятно.Дальнейшее обсуждение этого метода
Уловки с директивой препроцессора для новичков
источник
Интересно увидеть количество способов. вот тот, который я использовал давным-давно:
в файле myenummap.h:
в main.cpp
Это не const, но удобно.
Вот еще один способ, использующий возможности C ++ 11. Это const, не наследует контейнер STL и немного аккуратнее:
источник
Использование:
источник
MyEnum x = MyEnum::TWO;
. Я опубликовал свою правку вашего класса, чтобы поддержать это.Макрорешение Suma хорошее. Однако вам не обязательно иметь два разных макроса. C ++ с радостью включит заголовок дважды. Просто не включайте охранник.
Таким образом, у вас будет foobar.h, определяющий только
и вы бы включили это так:
enumfactory.h будет делать 2
#include ENUMFACTORY_ARGUMENT
с. В первом раунде он расширяет ENUM, как и SumaDECLARE_ENUM
; во втором раунде ENUM работает вродеDEFINE_ENUM
.Вы также можете включать enumfactory.h несколько раз, если вы передаете разные # define для ENUMFACTORY_ARGUMENT
источник
Обратите внимание, что в идеале ваша функция преобразования должна возвращать const char *.
Если вы можете позволить себе поместить свои перечисления в отдельные файлы заголовков, вы могли бы сделать что-то подобное с макросами (о, это будет некрасиво):
Где enum_def.h имеет:
И enum_conv.h имеет:
И, наконец, colour.h содержит:
И вы можете использовать функцию преобразования как:
Это уродливо, но это единственный способ (на уровне препроцессора), который позволяет вам определять ваше перечисление только в одном месте вашего кода. Таким образом, ваш код не подвержен ошибкам из-за изменений в перечислении. Ваше определение перечисления и функция преобразования всегда будут синхронизированы. Однако, повторяю, это некрасиво :)
источник
Другой ответ: в некоторых контекстах имеет смысл определить ваше перечисление в некодовом формате, таком как файл CSV, YAML или XML, а затем сгенерировать как код перечисления C ++, так и код преобразования из определения. Этот подход может быть практичным или непрактичным в вашем приложении, но об этом следует помнить.
источник
Это модификация ответа @ user3360260. Он имеет следующие новые функции
MyEnum fromString(const string&)
служба поддержкиИспользование:
Вот код
Обратите внимание, что преобразование toString - это быстрый поиск, а преобразование fromString - это медленный линейный поиск. Но в любом случае строки настолько дороги (и связанный с ними ввод-вывод файла), что я не чувствовал необходимости оптимизировать или использовать bimap.
источник
Здесь однофайловое решение (на основе элегантного ответа @Marcin:
источник
Я делаю это с помощью отдельных классов-оболочек перечисления бок о бок, которые генерируются с помощью макросов. Есть несколько преимуществ:
Обратной стороной, конечно же, является то, что мне нужно дублировать значения перечисления в классах средства форматирования, и у меня нет сценария для их генерации. Однако, в остальном, похоже, он работает довольно хорошо.
Вот пример перечисления из моей кодовой базы без всего кода фреймворка, который реализует макросы и шаблоны, но вы можете понять:
Идея состоит в том, что вместо использования EHelpLocation вы используете SEHelpLocation; все работает так же, но вы получаете проверку диапазона и метод Format () для самой переменной enum. Если вам нужно отформатировать автономное значение, вы можете использовать CEnumFormatter_EHelpLocation :: FormatEnum (...).
Надеюсь, это будет полезно. Я понимаю, что это также не решает исходный вопрос о сценарии для фактического создания другого класса, но я надеюсь, что эта структура поможет кому-то, пытаясь решить ту же проблему или написать такой сценарий.
источник
Это неизданное программное обеспечение, но похоже, что BOOST_ENUM от Фрэнка Лауба может соответствовать всем требованиям. Что мне нравится в этом, так это то, что вы можете определить перечисление в рамках класса, чего обычно не позволяют делать перечисления на основе макросов. Он находится в Boost Vault по адресу: http://www.boostpro.com/vault/index.php?action=downloadfile&filename=enum_rev4.6.zip&directory=& Он не претерпел никаких разработок с 2006 года, поэтому я не знать, насколько хорошо он компилируется с новыми выпусками Boost. Посмотрите в libs / test пример использования.
источник
Это было мое решение с BOOST:
Чтобы создать перечисление, объявите:
Для конверсий:
источник
Я хочу опубликовать это на случай, если кто-то сочтет это полезным.
В моем случае мне просто нужно сгенерировать
ToString()
иFromString()
функции для одного перечисления C ++ 11 из одного.hpp
файла.Я написал сценарий python, который анализирует файл заголовка, содержащий элементы перечисления, и генерирует функции в новом
.cpp
файле.Вы можете добавить этот сценарий в CMakeLists.txt с помощью execute_process или как событие перед сборкой в Visual Studio.
.cpp
Файл будет автоматически, без необходимости вручную обновлять его каждый раз , когда добавляется новый элемент перечисления.generate_enum_strings.py
Пример:
ErrorCode.hpp
Бегать
python generate_enum_strings.py ErrorCode.hpp
Результат:
ErrorCode.cpp
источник
Добавление еще большей простоты использования к фантастическому ответу Джаспера Беккерса :
Настроить один раз:
Затем для использования:
источник
Вы можете использовать библиотеку отражений, например Ponder . Вы регистрируете перечисления, а затем можете конвертировать их туда и обратно с помощью API.
источник
Проблема с ответом 0 заключается в том, что двоичные значения перечисления не обязательно начинаются с 0 и не обязательно являются смежными.
Когда мне это нужно, я обычно:
источник
Следующий скрипт ruby пытается проанализировать заголовки и построить необходимые источники вместе с исходными заголовками.
Использование регулярных выражений делает этот "синтаксический анализатор" довольно хрупким, он может быть не в состоянии правильно обрабатывать ваши конкретные заголовки.
Допустим, у вас есть заголовок toto / ah, содержащий определения для перечислений MyEnum и MyEnum2. Скрипт построит:
Более надежными решениями были бы:
источник
Это практически единственный способ сделать это (также может работать массив строк).
Проблема в том, что после компиляции программы на C используется только двоичное значение перечисления, а имя пропадает.
источник
Вот программа CLI, которую я написал, чтобы легко преобразовывать перечисления в строки. Его легко использовать, и на выполнение требуется около 5 секунд (включая время, необходимое для перехода к каталогу, содержащему программу, затем запустить его, передав ему файл, содержащий перечисление).
Скачать здесь: http://www.mediafire.com/?nttignoozzz
Тема обсуждения здесь: http://cboard.cprogramming.com/projects-job-recruitment/127488-free-program-im-sharing-convertenumtostrings.html
Запустите программу с аргументом "--help", чтобы получить описание того, как ее использовать.
источник
Не так давно я проделал трюк, чтобы перечисления правильно отображались в QComboBox и чтобы определение перечислений и строковых представлений было одним выражением.
Теперь у вас есть
enumeration::enum_singleton<your_enum>::instance()
возможность преобразовывать перечисления в строки. Если вы заменитеkv_storage_t
наboost::bimap
, вы также сможете выполнить обратное преобразование. Был введен общий базовый класс для конвертера, чтобы хранить его в объекте Qt, потому что объекты Qt не могли быть шаблонами.Предыдущее появление
источник
Как вариант, используйте простую библиотеку> http://codeproject.com/Articles/42035/Enum-to-String-and-Vice-Versa-in-C
В коде
добавить строки
Работает нормально, если значения в enum не дублируются .
Пример использования
и наоборот
источник
Вот попытка автоматически получить операторы потока << и >> в enum с помощью только однострочной макрос-команды ...
Определения:
Использование:
Не уверен в ограничениях этой схемы ... комментарии приветствуются!
источник
источник