Строгие перечисления в С++
От: Аноним  
Дата: 13.07.10 05:53
Оценка: 1152 (40)
Статья:
Строгие перечисления в С++
Автор(ы): Вьюков Дмитрий Сергеевич, Тепляков Сергей Владимирович
Дата: 13.07.2010
В данной статье рассмотрены несколько решений, позволяющих ослабить или практически полностью избавиться от недостатков перечислений (enumerations) языка программирования С++. Представленные решения, отличаются сложностью реализации и функциональностью, и могут оказаться полезными в арсенале каждого современного разработчика.


Авторы:
SergeyT.
remark

Аннотация:
В данной статье рассмотрены несколько решений, позволяющих ослабить или практически полностью избавиться от недостатков перечислений (enumerations) языка программирования С++. Представленные решения, отличаются сложностью реализации и функциональностью, и могут оказаться полезными в арсенале каждого современного разработчика.
Re: Строгие перечисления в С++
От: uzhas Ниоткуда  
Дата: 13.07.10 06:24
Оценка:
Здравствуйте, Вьюков Д. С., Тепляков С. В., Вы писали:

спасибо
самое большое решение тянет монстра под названием boost
радует объективный подход — перечисление как плюсов, так и минусов каждого решения
можно было еще осветить подход c++0x (привести пример кода, решающего те же самые задачи)
читатель мог бы взвесить что ему ближе — использовать boost или c++0x
и оценить, решает ли новый стандарт обыденные проблемы енумов или снова надо все обкладывать макросами
Re: Строгие перечисления в С++
От: kvser  
Дата: 13.07.10 08:18
Оценка:
В выводе результата выполнения второго примера использования строгого перечисления содержится ошибка

код:
d::cout << "Value: " << c.GetValue()
          << ", Internal name: " << c.InternalName()
          << ", External name: " << c.ExternalName() << std::endl;


результат:
Value: 1, Internal Name: Red,
Re: Строгие перечисления в С++
От: nen777w  
Дата: 13.07.10 08:28
Оценка:
Здравствуйте, Вьюков Д. С., Тепляков С. В., Вы писали:

ВДС>Статья:

ВДС>Строгие перечисления в С++
Автор(ы): Вьюков Дмитрий Сергеевич, Тепляков Сергей Владимирович
Дата: 13.07.2010
В данной статье рассмотрены несколько решений, позволяющих ослабить или практически полностью избавиться от недостатков перечислений (enumerations) языка программирования С++. Представленные решения, отличаются сложностью реализации и функциональностью, и могут оказаться полезными в арсенале каждого современного разработчика.


ВДС>Авторы:

ВДС> SergeyT.
ВДС> remark

ВДС>Аннотация:

ВДС>В данной статье рассмотрены несколько решений, позволяющих ослабить или практически полностью избавиться от недостатков перечислений (enumerations) языка программирования С++. Представленные решения, отличаются сложностью реализации и функциональностью, и могут оказаться полезными в арсенале каждого современного разработчика.

Спасибо статья хорошая.
В тему к перечислениям, Я активно использую вот такой вот классик.
linear enum converter
Автор: nen777w
Дата: 16.02.10


А вот его более свежая версия.
Добавилось то что теперь появились макросы которыми можно связывать не константные данные состояние которых можно изменить при вызове функции преобразования константы из enum-a к данным.
Мне например такое нужно было для отложенной подгруздки данных в приложение.

  Скрытый текст
#ifndef __linear_enum_convertor_h__
#define __linear_enum_convertor_h__

#include <assert.h>
#include <string.h>

//////////////////////////////////////////////////////////////////////////
#define BEGIN_COMPONENT_TBL_DECL( enum_type ) \
    typedef essence_description<enum_type>   S_CT_##enum_type; \
    static const S_CT_##enum_type enum_type##_list[] = {
//////////////////////////////////////////////////////////////////////////
#define BEGIN_COMPONENT_TBL_DECL_USER_TYPE( enum_type, user_t ) \
    typedef essence_description<enum_type, user_t>   S_CT_##enum_type##_##user_t; \
    static const S_CT_##enum_type##_##user_t enum_type##_##user_t##_list[] = {
//////////////////////////////////////////////////////////////////////////
#define BEGIN_NON_CONST_COMPONENT_TBL_DECL_USER_TYPE( enum_type, user_t ) \
    typedef essence_description<enum_type, user_t>   S_CT_##enum_type##_##user_t; \
    static S_CT_##enum_type##_##user_t enum_type##_##user_t##_list[] = {
//////////////////////////////////////////////////////////////////////////
#define REGISTER_ESSENCE_NAMED( component_id, name ) \
{ component_id, name },
//////////////////////////////////////////////////////////////////////////
#define REGISTER_ESSENCE( component_id ) \
{ component_id, #component_id },
//////////////////////////////////////////////////////////////////////////
#define REGISTER_ESSENCE_NAMED_USER_TYPE( component_id, name, user_value ) \
{ component_id, name, user_value },
//////////////////////////////////////////////////////////////////////////
#define REGISTER_ESSENCE_USER_TYPE( component_id, user_value ) \
{ component_id, #component_id, user_value },
//////////////////////////////////////////////////////////////////////////
#define REGISTER_ESSENCE_ONLY_USER_TYPE( component_id, user_value ) \
{ component_id, NULL, user_value },
//////////////////////////////////////////////////////////////////////////
#define END_COMPONENT_TBL_DECL( enum_type ) \
    }; \
    typedef string_2_enum<0, sizeof( enum_type##_list )/sizeof( S_CT_##enum_type )> s2e_##enum_type;
//////////////////////////////////////////////////////////////////////////
#define END_COMPONENT_TBL_DECL_USER_TYPE( enum_type, user_t ) \
   }; \
   typedef string_2_enum<0, sizeof( enum_type##_##user_t##_list )/sizeof( S_CT_##enum_type##_##user_t )> s2e_##enum_type##_##user_t;
//////////////////////////////////////////////////////////////////////////
#define IMPL_LINEAR_ZERO_BASED_S2E(convertor_ns, enum_type, method_name) \
    inline void method_name (const char * str, enum_type& value) \
    { \
        convertor_ns::s2e_##enum_type f; \
        value = f(convertor_ns::enum_type##_list, str); \
    }
//////////////////////////////////////////////////////////////////////////
#define IMPL_LINEAR_ZERO_BASED_E2S(convertor_ns, enum_type, method_name) \
    inline const char * method_name (enum_type value) \
    { \
        return convertor_ns::enum_type##_list[value]; \
    }
//////////////////////////////////////////////////////////////////////////
#define IMPL_LINEAR_ZERO_BASED_USER_TYPE_S2E(convertor_ns, enum_type, user_t, method_name) \
    inline void method_name (const char * str, enum_type& value) \
    { \
        convertor_ns##::##s2e_##enum_type##_##user_t f; \
        value = f(convertor_ns##::##enum_type##_##user_t##_##list, str); \
    }
//////////////////////////////////////////////////////////////////////////
#define IMPL_LINEAR_ZERO_BASED_USER_TYPE_E2S(convertor_ns, enum_type, user_t, method_name) \
    inline const char * method_name (enum_type value) \
    { \
        return convertor_ns##::##enum_type##_##user_t##_list[value]; \
    }
//////////////////////////////////////////////////////////////////////////
#define IMPL_LINEAR_ZERO_BASED_USER_TYPE_E2DATA(convertor_ns, enum_type, user_t, method_name) \
    inline const convertor_ns##::##user_t * method_name (enum_type value) \
    { \
        return &convertor_ns##::##enum_type##_##user_t##_list[value].info; \
    }
//////////////////////////////////////////////////////////////////////////
#define IMPL_LINEAR_ZERO_BASED_USER_TYPE_E2DATA_CHANGER(convertor_ns, enum_type, user_t, changer, method_name) \
    inline const convertor_ns##::##user_t * method_name (enum_type value) \
    { \
        changer(&convertor_ns##::##enum_type##_##user_t##_list[value].info); \
        return &convertor_ns##::##enum_type##_##user_t##_list[value].info; \
    }
//////////////////////////////////////////////////////////////////////////
#define IMPL_LINEAR_ZERO_BASED_CONVERTION_PAIR(convertor_ns, enum_type) \
    IMPL_LINEAR_ZERO_BASED_S2E(convertor_ns, enum_type, string2enum) \
    IMPL_LINEAR_ZERO_BASED_E2S(convertor_ns, enum_type, enum2string)
//////////////////////////////////////////////////////////////////////////
#define IMPL_LINEAR_ZERO_BASED_CONVERTION_PAIR_USER_TYPE(convertor_ns, enum_type, user_t) \
    IMPL_LINEAR_ZERO_BASED_USER_TYPE_S2E(convertor_ns, enum_type, user_t, string2enum) \
    IMPL_LINEAR_ZERO_BASED_USER_TYPE_E2S(convertor_ns, enum_type, user_t, enum2string) \
    IMPL_LINEAR_ZERO_BASED_USER_TYPE_E2DATA(convertor_ns, enum_type, user_t, enum2data)
//////////////////////////////////////////////////////////////////////////

//converter--------------------------------------------

struct  dummy {};

template< typename T, typename TExInfo = dummy >
struct essence_description {
    typedef T            value_type;
    typedef TExInfo      ex_info_type;
    typedef const char*  c_char_ptr;
    
    //dont change the members order
    T           code;
    c_char_ptr  name;
    TExInfo     info;

    inline operator c_char_ptr() const { return name; }
};

template< int first_value, int last_value >
struct string_2_enum 
{
    template< typename T, typename TExInfo >
    inline typename essence_description<T, TExInfo>::value_type operator()
        ( 
        const essence_description<T, TExInfo> arr[], const char* str 
        ) 
    {
        int t1 = first_value;
        for( ; t1 < last_value; ++t1 ) {
            if( strcmp( str, arr[t1].name) == 0 )
                return typename essence_description<T, TExInfo>::value_type(t1);
        }

        //можно было бы бросить исключение, или что то по информативней
        assert(!"Out of range");
        return typename essence_description<T, TExInfo>::value_type(first_value);
    }
};

//////////////////////////////////////////////////////////////////////////

#endif
Re: Строгие перечисления в С++
От: jazzer Россия Skype: enerjazzer
Дата: 13.07.10 09:24
Оценка:
Здравствуйте, Вьюков Д. С., Тепляков С. В., Вы писали:

ВДС>Статья:

ВДС>Строгие перечисления в С++
Автор(ы): Вьюков Дмитрий Сергеевич, Тепляков Сергей Владимирович
Дата: 13.07.2010
В данной статье рассмотрены несколько решений, позволяющих ослабить или практически полностью избавиться от недостатков перечислений (enumerations) языка программирования С++. Представленные решения, отличаются сложностью реализации и функциональностью, и могут оказаться полезными в арсенале каждого современного разработчика.


А почему не упомянута предлагавшаяся в Буст библиотека Boost.Enum, раз уж дан обзор?
http://www.boostpro.com/vault/, файл enum_rev4.6.zip (последняя версия, от 17.01.2006)

прямой линк на архив для скачивания:
http://www.boostpro.com/vault/index.php?action=downloadfile&amp;filename=enum_rev4.6.zip&amp;directory=&amp;PHPSESSID=00a1d7dd87d9892a3eb2c0fa6ee07f91
jazzer (Skype: enerjazzer) Ночная тема для RSDN
Автор: jazzer
Дата: 26.11.09

You will always get what you always got
  If you always do  what you always did
Re: Строгие перечисления в С++
От: _FRED_ Черногория
Дата: 13.07.10 13:41
Оценка:
Здравствуйте, Вьюков Д. С., Тепляков С. В., Вы писали:

ВДС>Статья:

ВДС>Строгие перечисления в С++
Автор(ы): Вьюков Дмитрий Сергеевич, Тепляков Сергей Владимирович
Дата: 13.07.2010
В данной статье рассмотрены несколько решений, позволяющих ослабить или практически полностью избавиться от недостатков перечислений (enumerations) языка программирования С++. Представленные решения, отличаются сложностью реализации и функциональностью, и могут оказаться полезными в арсенале каждого современного разработчика.


ВДС>Авторы:

ВДС> SergeyT.
ВДС> remark

Уважаемая редакция!

Отредактируйте, пожалуйста, раздел "Литература
Автор(ы): Вьюков Дмитрий Сергеевич, Тепляков Сергей Владимирович
Дата: 13.07.2010
В данной статье рассмотрены несколько решений, позволяющих ослабить или практически полностью избавиться от недостатков перечислений (enumerations) языка программирования С++. Представленные решения, отличаются сложностью реализации и функциональностью, и могут оказаться полезными в арсенале каждого современного разработчика.
", ссылку под номером шесть: она ведёт не туда, куда нужно.
Help will always be given at Hogwarts to those who ask for it.
Re: Строгие перечисления в С++
От: Vain Россия google.ru
Дата: 13.07.10 13:44
Оценка: :)
Здравствуйте, Вьюков Д. С., Тепляков С. В., Вы писали:

ВДС>Статья:

ВДС>Строгие перечисления в С++
Автор(ы): Вьюков Дмитрий Сергеевич, Тепляков Сергей Владимирович
Дата: 13.07.2010
В данной статье рассмотрены несколько решений, позволяющих ослабить или практически полностью избавиться от недостатков перечислений (enumerations) языка программирования С++. Представленные решения, отличаются сложностью реализации и функциональностью, и могут оказаться полезными в арсенале каждого современного разработчика.

ВДС>Авторы:
ВДС> SergeyT.
ВДС> remark
ВДС>Аннотация:
ВДС>В данной статье рассмотрены несколько решений, позволяющих ослабить или практически полностью избавиться от недостатков перечислений (enumerations) языка программирования С++. Представленные решения, отличаются сложностью реализации и функциональностью, и могут оказаться полезными в арсенале каждого современного разработчика.
Забавные оценки.
[In theory there is no difference between theory and practice. In
practice there is.]
[Даю очевидные ответы на риторические вопросы]
Re: Строгие перечисления в С++
От: bnk СССР http://unmanagedvisio.com/
Дата: 13.07.10 18:03
Оценка: +2
Здравствуйте, Вьюков Д. С., Тепляков С. В., Вы писали:

ВДС>Аннотация:

ВДС>В данной статье рассмотрены несколько решений, позволяющих ослабить или практически полностью избавиться от недостатков перечислений (enumerations) языка программирования С++. Представленные решения, отличаются сложностью реализации и функциональностью, и могут оказаться полезными в арсенале каждого современного разработчика.

Вот честно не представляю, зачем может понадобиться что-то сложнее первого варианта, описанного в статье, кроме академических изысков
То есть, по мне, так вот это:

enum Option
{
    Option_One, 
    Option_Two,

    Option_Count
}

решает большинство задач встречающихся в народном хозяйстве,
включая автокомплит/именование и перечисление всех элементов (0 < i < Option_Count).
Ради чего плодить кучу безумных макросов??

Проблемы которые вижу со всеми остальными вариантами:
— Часто енумы используются как "флаги" ([Flags] в C#) , однако вариант (Option::One|Option::Two) не скомпилируется, нужен кастинг или еще экран кода с операторами "|".
— Такие енумы несовместимы с кодом на C, или с кодом на IDL.
— Для определения строготипизированного енума тупо придется писать больше неудобочитаемого текста.

Все IMHO, конечно
Re[2]: Строгие перечисления в С++
От: Vain Россия google.ru
Дата: 13.07.10 19:53
Оценка:
Здравствуйте, bnk, Вы писали:

ВДС>>Аннотация:

ВДС>>В данной статье рассмотрены несколько решений, позволяющих ослабить или практически полностью избавиться от недостатков перечислений (enumerations) языка программирования С++. Представленные решения, отличаются сложностью реализации и функциональностью, и могут оказаться полезными в арсенале каждого современного разработчика.
bnk>Вот честно не представляю, зачем может понадобиться что-то сложнее первого варианта, описанного в статье, кроме академических изысков
bnk>То есть, по мне, так вот это:
bnk>
bnk>enum Option
bnk>{
bnk>    Option_One, 
bnk>    Option_Two,

bnk>    Option_Count
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.]
[Даю очевидные ответы на риторические вопросы]
Re[3]: Строгие перечисления в С++
От: bnk СССР http://unmanagedvisio.com/
Дата: 13.07.10 20:44
Оценка: +3
Здравствуйте, Vain, Вы писали:

V>Решает, но иногда надо связать с енумом строковые литералы, что, имхо, и продемонстрировано. Хотя я считаю пример надуманным, т.к. если и надо строковые литералы к енумам привязать, то либо это надо делать в рантайме, либо до него. Если до него, то никакие типы из рантайма (std::string) не должны использоваться, если в рантайме, то зачем тогда макросы? Имхо, если уж так хочется в точке объявления всё писать, то незачем тащить std::string туда, где он не нужен, можно спокойно обойтись boost::preprocessor в полной мере.


Я за рантайм. Ну не растут у нас лимоны, ну и фиг с ними, какой смысл их в горшочках выращивать... Разве что из спортивного интереса.
Сравним код выше с очевидным вариантом. Какой будет легче поддерживать? В общем, не доходят до меня пока эти изыски...

enum Option { Option_One, Option_Two, Option_Count };

const char* getOptionValue(Option option)
{
    switch (option)
    {
    case Option_One:    return "Value1";
    case Option_Two:    return "Value2";
    }
}
Re[4]: Строгие перечисления в С++
От: Vain Россия google.ru
Дата: 13.07.10 21:06
Оценка:
Здравствуйте, 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.]
[Даю очевидные ответы на риторические вопросы]
Re[5]: Строгие перечисления в С++
От: bnk СССР http://unmanagedvisio.com/
Дата: 13.07.10 22:29
Оценка:
Здравствуйте, 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 "";
}
Re[6]: Строгие перечисления в С++
От: Vain Россия google.ru
Дата: 14.07.10 00:16
Оценка:
Здравствуйте, 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.]
[Даю очевидные ответы на риторические вопросы]
Re: Строгие перечисления в С++
От: zaufi Земля  
Дата: 14.07.10 14:10
Оценка:
Здравствуйте, Вьюков Д. С., Тепляков С. В., Вы писали:

ПРИМЕЧАНИЕ

На самом деле, sizeof(e1) может равняться 1, 2 или 4 (а не только 1 или 4, как об этом пишет Страуструп), но не 8


#include <iostream>
using namespace std;

enum a { z = 1234567890123456L };
enum b { x = 1 };

int main()
{
    cout << sizeof(a) << endl;
    cout << sizeof(b) << endl;
    return 0;
}


$ ./test
8
4


??? <- это мой молчаливый вопрос оставшийся после прочтения примечания...
Re[2]: Строгие перечисления в С++
От: SergeyT. США http://sergeyteplyakov.blogspot.com/
Дата: 14.07.10 18:28
Оценка:
Здравствуйте, 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. Так ведь?
Re[5]: Строгие перечисления в С++
От: Vamp Россия  
Дата: 27.07.10 17:55
Оценка:
V>Здесь можно забыть добавить case для свитча.
В принципе, здесь неплохо работает кодогенерация из какого-нибудь описательного формата в C++, как pre-build шаг.
Да здравствует мыло душистое и веревка пушистая.
Re[3]: Собираются ли последние версии QT в Visual Studio ?
От: rsdntchkru  
Дата: 04.08.10 10:09
Оценка:
Здравствуйте, Vain, Вы писали:


V>Решает, но иногда надо связать с енумом строковые литералы, что, имхо, и продемонстрировано. Хотя я считаю пример надуманным, т.к. если и надо строковые литералы к енумам привязать, то либо это надо делать в рантайме, либо до него. Если до него, то никакие типы из рантайма (std::string) не должны использоваться, если в рантайме, то зачем тогда макросы? Имхо, если уж так хочется в точке объявления всё писать, то незачем тащить std::string туда, где он не нужен, можно спокойно обойтись boost::preprocessor в полной мере.

V>Примерно так можно:
V>
V>#include <stdio.h>

V>template<const char* (*pfunc)()>
V>struct EnumStringValueA
V>{
V>    const char* value;

V>    EnumStringValueA()
V>    {
V>        value = (*pfunc)();
V>    }
V>};

V>class MyEnumImpl
V>{
V>public:
V>    enum type { Value1 = 1, Value2 = 10 };

V>protected:
V>    template<int dummy>
V>    class names_tmpl
V>    {
V>    public:
V>        static const char* get_Value1() { return "Value1"; }
V>        static const char* get_Value2() { return "Value2"; }

V>        //Names are the same as names from wrapped enumeration.
V>        static EnumStringValueA<&names_tmpl::get_Value1> Value1;
V>        static EnumStringValueA<&names_tmpl::get_Value2> Value2;
V>    };

V>    template<int dummy>
V>    class descs_tmpl
V>    {
V>    public:
V>        static const char* get_Value1() { return "My desc 1"; }
V>        static const char* get_Value2() { return "My desc 2"; }

V>        //Names are the same as names from wrapped enumeration.
V>        static EnumStringValueA<&descs_tmpl::get_Value1> Value1;
V>        static EnumStringValueA<&descs_tmpl::get_Value2> Value2;
V>    };

V>public:
V>    typedef names_tmpl<0> names;
V>    typedef descs_tmpl<0> descs;
V>};

V>template<int dummy>
V>EnumStringValueA<&MyEnumImpl::names_tmpl<dummy>::get_Value1> MyEnumImpl::names_tmpl<dummy>::Value1;
V>template<int dummy>
V>EnumStringValueA<&MyEnumImpl::names_tmpl<dummy>::get_Value2> MyEnumImpl::names_tmpl<dummy>::Value2;

V>template<int dummy>
V>EnumStringValueA<&MyEnumImpl::descs_tmpl<dummy>::get_Value1> MyEnumImpl::descs_tmpl<dummy>::Value1;
V>template<int dummy>
V>EnumStringValueA<&MyEnumImpl::descs_tmpl<dummy>::get_Value2> MyEnumImpl::descs_tmpl<dummy>::Value2;

V>int main()
V>{
V>    //Example of usage #1.
V>    printf("%s = {%i, \"%s\"};\n",MyEnumImpl::names::Value1.value,MyEnumImpl::Value1,MyEnumImpl::descs::Value1.value);

V>    //Example of usage #2.
V>    printf("%s = {%i, \"%s\"};\n",MyEnumImpl::names::get_Value2(),MyEnumImpl::Value2,MyEnumImpl::descs::get_Value2());

V>    return 0;
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 месяца руководствуясь подобными парадигмами, в репозиторий не коммитил а потом выдал результат, что все упали. Модуль проработал в релизе до первого баг-репорта, потом пришлось все выкинуть и переписать заново (так было быстрее).

я за вариант bnk:

enum Option { Option_One, Option_Two, Option_Count };

const char* getOptionValue(Option option)
{
    switch (option)
    {
    case Option_One:    return "Value1";
    case Option_Two:    return "Value2";
    }
}
Re[4]: Собираются ли последние версии QT в Visual Studio ?
От: Vain Россия google.ru
Дата: 04.08.10 11:28
Оценка:
Здравствуйте, 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 ?
От: rsdntchkru  
Дата: 04.08.10 13:21
Оценка: :)
Здравствуйте, Vain, Вы писали:

V>Здравствуйте, rsdntchkru, Вы писали:


V>>>...

V>>>Можно ещё наворотов добавить, вроде итератора по значениям енума (через boost::mpl) и перегрузить операторы, чтобы делать операции над значениями енума.
R>>ужос! это пример как из простого сделать нечитабельно-неподдерживаемое сложное?
V>Вы вариант remark'а видели? Так ещё больший ужос, лучше вам в программирование нос не совать, там много ужософ ходят..

Да уж, наверно надо было не совать. К сожалению как 17 лет назад засунул, так все там. И все еще не перстаю порой удивляться ширине пытливой мысли некоторых программистов типа как приведенной в варианте 4 этой статьи. Если из обычного enuma такую тему можно было развить, то что будет если они код для пузырьковой сортировки опишут? Роман на 500 листов
Re[6]: Собираются ли последние версии QT в Visual Studio ?
От: Vain Россия google.ru
Дата: 04.08.10 21:31
Оценка:
Здравствуйте, 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.]
[Даю очевидные ответы на риторические вопросы]
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.