Аннотация:
В данной статье рассмотрены несколько решений, позволяющих ослабить или практически полностью избавиться от недостатков перечислений (enumerations) языка программирования С++. Представленные решения, отличаются сложностью реализации и функциональностью, и могут оказаться полезными в арсенале каждого современного разработчика.
Здравствуйте, Вьюков Д. С., Тепляков С. В., Вы писали:
спасибо
самое большое решение тянет монстра под названием boost
радует объективный подход — перечисление как плюсов, так и минусов каждого решения
можно было еще осветить подход c++0x (привести пример кода, решающего те же самые задачи)
читатель мог бы взвесить что ему ближе — использовать boost или c++0x
и оценить, решает ли новый стандарт обыденные проблемы енумов или снова надо все обкладывать макросами
ВДС>Авторы: ВДС> SergeyT. ВДС> remark ВДС>Аннотация: ВДС>В данной статье рассмотрены несколько решений, позволяющих ослабить или практически полностью избавиться от недостатков перечислений (enumerations) языка программирования С++. Представленные решения, отличаются сложностью реализации и функциональностью, и могут оказаться полезными в арсенале каждого современного разработчика.
Спасибо статья хорошая.
В тему к перечислениям, Я активно использую вот такой вот классик. linear enum converter
А вот его более свежая версия.
Добавилось то что теперь появились макросы которыми можно связывать не константные данные состояние которых можно изменить при вызове функции преобразования константы из enum-a к данным.
Мне например такое нужно было для отложенной подгруздки данных в приложение.
А почему не упомянута предлагавшаяся в Буст библиотека Boost.Enum, раз уж дан обзор? http://www.boostpro.com/vault/, файл enum_rev4.6.zip (последняя версия, от 17.01.2006)
ВДС>Авторы: ВДС> SergeyT. ВДС> remark ВДС>Аннотация: ВДС>В данной статье рассмотрены несколько решений, позволяющих ослабить или практически полностью избавиться от недостатков перечислений (enumerations) языка программирования С++. Представленные решения, отличаются сложностью реализации и функциональностью, и могут оказаться полезными в арсенале каждого современного разработчика.
Забавные оценки.
[In theory there is no difference between theory and practice. In
practice there is.]
[Даю очевидные ответы на риторические вопросы]
Здравствуйте, Вьюков Д. С., Тепляков С. В., Вы писали:
ВДС>Аннотация: ВДС>В данной статье рассмотрены несколько решений, позволяющих ослабить или практически полностью избавиться от недостатков перечислений (enumerations) языка программирования С++. Представленные решения, отличаются сложностью реализации и функциональностью, и могут оказаться полезными в арсенале каждого современного разработчика.
Вот честно не представляю, зачем может понадобиться что-то сложнее первого варианта, описанного в статье, кроме академических изысков
То есть, по мне, так вот это:
решает большинство задач встречающихся в народном хозяйстве,
включая автокомплит/именование и перечисление всех элементов (0 < i < Option_Count).
Ради чего плодить кучу безумных макросов??
Проблемы которые вижу со всеми остальными вариантами:
— Часто енумы используются как "флаги" ([Flags] в C#) , однако вариант (Option::One|Option::Two) не скомпилируется, нужен кастинг или еще экран кода с операторами "|".
— Такие енумы несовместимы с кодом на C, или с кодом на IDL.
— Для определения строготипизированного енума тупо придется писать больше неудобочитаемого текста.
Здравствуйте, bnk, Вы писали:
ВДС>>Аннотация: ВДС>>В данной статье рассмотрены несколько решений, позволяющих ослабить или практически полностью избавиться от недостатков перечислений (enumerations) языка программирования С++. Представленные решения, отличаются сложностью реализации и функциональностью, и могут оказаться полезными в арсенале каждого современного разработчика. bnk>Вот честно не представляю, зачем может понадобиться что-то сложнее первого варианта, описанного в статье, кроме академических изысков bnk>То есть, по мне, так вот это: bnk>
bnk>решает большинство задач встречающихся в народном хозяйстве, bnk>включая автокомплит/именование и перечисление всех элементов (0 < i < Option_Count). bnk>Ради чего плодить кучу безумных макросов??
Решает, но иногда надо связать с енумом строковые литералы, что, имхо, и продемонстрировано. Хотя я считаю пример надуманным, т.к. если и надо строковые литералы к енумам привязать, то либо это надо делать в рантайме, либо до него. Если до него, то никакие типы из рантайма (std::string) не должны использоваться, если в рантайме, то зачем тогда макросы? Имхо, если уж так хочется в точке объявления всё писать, то незачем тащить std::string туда, где он не нужен, можно спокойно обойтись boost::preprocessor в полной мере.
Примерно так можно:
#include <stdio.h>
template<const char* (*pfunc)()>
struct EnumStringValueA
{
const char* value;
EnumStringValueA()
{
value = (*pfunc)();
}
};
class MyEnumImpl
{
public:
enum type { Value1 = 1, Value2 = 10 };
protected:
template<int dummy>
class names_tmpl
{
public:
static const char* get_Value1() { return"Value1"; }
static const char* get_Value2() { return"Value2"; }
//Names are the same as names from wrapped enumeration.static EnumStringValueA<&names_tmpl::get_Value1> Value1;
static EnumStringValueA<&names_tmpl::get_Value2> Value2;
};
template<int dummy>
class descs_tmpl
{
public:
static const char* get_Value1() { return"My desc 1"; }
static const char* get_Value2() { return"My desc 2"; }
//Names are the same as names from wrapped enumeration.static EnumStringValueA<&descs_tmpl::get_Value1> Value1;
static EnumStringValueA<&descs_tmpl::get_Value2> Value2;
};
public:
typedef names_tmpl<0> names;
typedef descs_tmpl<0> descs;
};
template<int dummy>
EnumStringValueA<&MyEnumImpl::names_tmpl<dummy>::get_Value1> MyEnumImpl::names_tmpl<dummy>::Value1;
template<int dummy>
EnumStringValueA<&MyEnumImpl::names_tmpl<dummy>::get_Value2> MyEnumImpl::names_tmpl<dummy>::Value2;
template<int dummy>
EnumStringValueA<&MyEnumImpl::descs_tmpl<dummy>::get_Value1> MyEnumImpl::descs_tmpl<dummy>::Value1;
template<int dummy>
EnumStringValueA<&MyEnumImpl::descs_tmpl<dummy>::get_Value2> MyEnumImpl::descs_tmpl<dummy>::Value2;
int main()
{
//Example of usage #1.
printf("%s = {%i, \"%s\"};\n",MyEnumImpl::names::Value1.value,MyEnumImpl::Value1,MyEnumImpl::descs::Value1.value);
//Example of usage #2.
printf("%s = {%i, \"%s\"};\n",MyEnumImpl::names::get_Value2(),MyEnumImpl::Value2,MyEnumImpl::descs::get_Value2());
return 0;
}
Естесственно, MyEnumImpl вставляется через примерно такой макрос:
#define DEFINE_STRICT_ENUM_BLA_BLA(enumClassName,(Value1,1,"My desc 1")(Value2,10,"My desc 2")) \
class enumClassName ...
//enumClassName здесь это сгенерированный на лету MyEnumImpl.
Можно ещё наворотов добавить, вроде итератора по значениям енума (через boost::mpl) и перегрузить операторы, чтобы делать операции над значениями енума.
[In theory there is no difference between theory and practice. In
practice there is.]
[Даю очевидные ответы на риторические вопросы]
Здравствуйте, Vain, Вы писали:
V>Решает, но иногда надо связать с енумом строковые литералы, что, имхо, и продемонстрировано. Хотя я считаю пример надуманным, т.к. если и надо строковые литералы к енумам привязать, то либо это надо делать в рантайме, либо до него. Если до него, то никакие типы из рантайма (std::string) не должны использоваться, если в рантайме, то зачем тогда макросы? Имхо, если уж так хочется в точке объявления всё писать, то незачем тащить std::string туда, где он не нужен, можно спокойно обойтись boost::preprocessor в полной мере.
Я за рантайм. Ну не растут у нас лимоны, ну и фиг с ними, какой смысл их в горшочках выращивать... Разве что из спортивного интереса.
Сравним код выше с очевидным вариантом. Какой будет легче поддерживать? В общем, не доходят до меня пока эти изыски...
Здравствуйте, bnk, Вы писали:
bnk>Я за рантайм. Ну не растут у нас лимоны, ну и фиг с ними, какой смысл их в горшочках выращивать... Разве что из спортивного интереса. bnk>Сравним код выше с очевидным вариантом. Какой будет легче поддерживать? В общем, не доходят до меня пока эти изыски... bnk>enum Option { Option_One, Option_Two, Option_Count };
Здесь можно забыть обновить Option_Count, если значения явно заданы для енума и не последовательно идут.
bnk>const char* getOptionValue(Option option) bnk>{ bnk> switch (option) bnk> { bnk> case Option_One: return "Value1"; bnk> case Option_Two: return "Value2"; bnk> } bnk>}
Здесь можно забыть добавить case для свитча.
[In theory there is no difference between theory and practice. In
practice there is.]
[Даю очевидные ответы на риторические вопросы]
Здравствуйте, Vain, Вы писали:
bnk>>enum Option { Option_One, Option_Two, Option_Count }; V>Здесь можно забыть обновить Option_Count, если значения явно заданы для енума и не последовательно идут.
Если значения явно заданы для енума и непоследовательно,
то Option_Count вообще не имеет никакого смысла, и его нужно тупо удалить.
bnk>> case Option_One: return "Value1"; bnk>> case Option_Two: return "Value2";
V>Здесь можно забыть добавить case для свитча.
Безусловно. Это минус. При добавлении нового элемента можно забыть обновить.
Однако с другой стороны, зачем-то же новый элемент добавляется, и все равно (скорее всего) придется просматривать места где этот енум используется.
А минимальную страховку от забывчивости конечно надо добавить.
switch (option)
{
case Option_One: return"value1";
case Option_Two: return"value2";
default:
assert(!"boo");
return"";
}
Здравствуйте, bnk, Вы писали:
bnk>>>enum Option { Option_One, Option_Two, Option_Count }; V>>Здесь можно забыть обновить Option_Count, если значения явно заданы для енума и не последовательно идут. bnk>Если значения явно заданы для енума и непоследовательно, bnk>то Option_Count вообще не имеет никакого смысла, и его нужно тупо удалить.
Даже в этом случае не факт, значения могут перебираться через заранее проинициализированный массив, а for без размера бесполезен.
bnk>>> case Option_One: return "Value1"; bnk>>> case Option_Two: return "Value2"; V>>Здесь можно забыть добавить case для свитча. bnk>Безусловно. Это минус. При добавлении нового элемента можно забыть обновить. bnk>Однако с другой стороны, зачем-то же новый элемент добавляется, и все равно (скорее всего) придется просматривать места где этот енум используется.
Вот именно, а так есть гарантии что не забудете, т.е. "либо всё, либо ничего".
bnk>А минимальную страховку от забывчивости конечно надо добавить.
Ну это само собой
[In theory there is no difference between theory and practice. In
practice there is.]
[Даю очевидные ответы на риторические вопросы]
Здравствуйте, zaufi, Вы писали:
Z>??? <- это мой молчаливый вопрос оставшийся после прочтения примечания...
Примечание относится к следующей цитате Страуструпа:
«Размер (sizeof) перечисления является размером некоторого интегрального типа, который в состоянии содержать весь диапазон значений перечисления. Результат не больше, чем sizeof(int) при условии, что элементы перечисления представимы в виде int или unsigned int. Например, sizeof(e1) может равняться 1 или 4, но не 8 на машине, где sizeof(int) == 4.»
Мы в примечании расширили исходную цитату Страуструпа добавив туда еще и 2, т.е. было "1 или 4, но не 8", стало "1, 2 или 4, но не 8", при этом завершение исходной фразы "где sizeof(int) == 4" мы опустили, за ненадобностью; других целей у примечания не было. А в вашем же случае, sizeof(int) как раз, наверное, и равен 8. Так ведь?
V>Здесь можно забыть добавить case для свитча.
В принципе, здесь неплохо работает кодогенерация из какого-нибудь описательного формата в C++, как pre-build шаг.
Да здравствует мыло душистое и веревка пушистая.
Re[3]: Собираются ли последние версии QT в Visual Studio ?
V>Решает, но иногда надо связать с енумом строковые литералы, что, имхо, и продемонстрировано. Хотя я считаю пример надуманным, т.к. если и надо строковые литералы к енумам привязать, то либо это надо делать в рантайме, либо до него. Если до него, то никакие типы из рантайма (std::string) не должны использоваться, если в рантайме, то зачем тогда макросы? Имхо, если уж так хочется в точке объявления всё писать, то незачем тащить std::string туда, где он не нужен, можно спокойно обойтись boost::preprocessor в полной мере. V>Примерно так можно: V>
V>Естесственно, MyEnumImpl вставляется через примерно такой макрос: V>
V>#define DEFINE_STRICT_ENUM_BLA_BLA(enumClassName,(Value1,1,"My desc 1")(Value2,10,"My desc 2")) \
V>class enumClassName ...
V>//enumClassName здесь это сгенерированный на лету MyEnumImpl.
V>
V>Можно ещё наворотов добавить, вроде итератора по значениям енума (через boost::mpl) и перегрузить операторы, чтобы делать операции над значениями енума.
ужос! это пример как из простого сделать нечитабельно-неподдерживаемое сложное?
помню у нас был один такой умелец, закрылся в своей комнатушке и писал модуль 3 месяца руководствуясь подобными парадигмами, в репозиторий не коммитил а потом выдал результат, что все упали. Модуль проработал в релизе до первого баг-репорта, потом пришлось все выкинуть и переписать заново (так было быстрее).
Здравствуйте, rsdntchkru, Вы писали:
V>>... V>>Можно ещё наворотов добавить, вроде итератора по значениям енума (через boost::mpl) и перегрузить операторы, чтобы делать операции над значениями енума. R>ужос! это пример как из простого сделать нечитабельно-неподдерживаемое сложное?
Вы вариант remark'а видели? Так ещё больший ужос, лучше вам в программирование нос не совать, там много ужософ ходят..
[In theory there is no difference between theory and practice. In
practice there is.]
[Даю очевидные ответы на риторические вопросы]
Re[5]: Собираются ли последние версии QT в Visual Studio ?
Здравствуйте, Vain, Вы писали:
V>Здравствуйте, rsdntchkru, Вы писали:
V>>>... V>>>Можно ещё наворотов добавить, вроде итератора по значениям енума (через boost::mpl) и перегрузить операторы, чтобы делать операции над значениями енума. R>>ужос! это пример как из простого сделать нечитабельно-неподдерживаемое сложное? V>Вы вариант remark'а видели? Так ещё больший ужос, лучше вам в программирование нос не совать, там много ужософ ходят..
Да уж, наверно надо было не совать. К сожалению как 17 лет назад засунул, так все там. И все еще не перстаю порой удивляться ширине пытливой мысли некоторых программистов типа как приведенной в варианте 4 этой статьи. Если из обычного enuma такую тему можно было развить, то что будет если они код для пузырьковой сортировки опишут? Роман на 500 листов
Re[6]: Собираются ли последние версии QT в Visual Studio ?
Здравствуйте, rsdntchkru, Вы писали:
V>>>>... V>>>>Можно ещё наворотов добавить, вроде итератора по значениям енума (через boost::mpl) и перегрузить операторы, чтобы делать операции над значениями енума. R>>>ужос! это пример как из простого сделать нечитабельно-неподдерживаемое сложное? V>>Вы вариант remark'а видели? Так ещё больший ужос, лучше вам в программирование нос не совать, там много ужософ ходят.. R>Да уж, наверно надо было не совать. К сожалению как 17 лет назад засунул, так все там. И все еще не перстаю порой удивляться ширине пытливой мысли некоторых программистов типа как приведенной в варианте 4 этой статьи. Если из обычного enuma такую тему можно было развить, то что будет если они код для пузырьковой сортировки опишут? Роман на 500 листов
Не будет романов, std::sort решает в большинстве, похоже за 17 лет вы не в курсе про него
[In theory there is no difference between theory and practice. In
practice there is.]
[Даю очевидные ответы на риторические вопросы]