Re[3]: [Trick] Делаем правильные enum'ы
От: Аноним  
Дата: 07.09.07 07:47
Оценка:
Здравствуйте, Erop, Вы писали:

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


M>>Еще одна большая проблема это смешивание значений разных енумов. Значение одного енума можно присвоить по ошибке другому енуму. Собственно с этой проблемой тоже бы неплохо бороться статической типизацией.


E>Разве так можно?
 enum E1 { E11, E12 };
E>enum E2 { E21, E22 };
E>E2 var = E11; // тут не компилируется вроде


Зато многое другое компилируется на ура.
У енумов проблем вагон и маленькая тележка.
Re[2]: [Trick] Делаем правильные enum'ы
От: vitalyk  
Дата: 07.09.07 13:59
Оценка: 3 (1)
Здравствуйте, igna, Вы писали:

I>
R>>typedef right_enum<color_def> color;
I>


I>Неприятно, что виден color_def, а в нем еще и type.


В 2005-й студии работает такое :

#define explicit_enum(enum_name)\
struct enum_name { \
    enum type; \
    enum_name( type v ) : m_v( v ) {} \
  type m_v; \
    operator type() const { return m_v; } \
}; \
    enum enum_name::type


explicit_enum( Colors )
{
  Red,
  Green,
  Blue
};
    
...

Colors color = Colors::Red;


Естественно, код не соответствует стандарту, Comeau, например, не компилит. Зато ничего лишнего не видно
... << RSDN@Home 1.2.0 alpha rev. 743>>
Re: [Trick] Делаем правильные enum'ы
От: _nn_ www.nemerleweb.com
Дата: 07.09.07 14:22
Оценка: 37 (6)
Здравствуйте, remark, Вы писали:

R>Наверное многие задавались вопросом — почему сделано так странно и нелогично, почему enum'ы выносят имена своих констант в окружающее пространство имён, хотя объявлены константы вроде как внутри самого enum'а?


В Boost.Vault есть реализация вашей идеи: Boost.Enum.

Примеры использования:
struct Log
{
    BOOST_ENUM_VALUES(Level, const char*,
        (Abort)("unrecoverable problem") 
        (Error)("recoverable problem")   
        (Alert)("unexpected behavior") 
        (Info) ("expected behavior") 
        (Trace)("normal flow of execution") 
        (Debug)("detailed object state listings") 
    )
};

BOOST_ENUM(boolean, 
    (False)
    (True) 
)

BOOST_ENUM_VALUES(VirtualKey, int,
    (Zero) (0)
    (Space)(0x20)
    (Prior)(0x21)
    (Next) (0x22)
    (End)  (0x23)
    (Home) (0x24)
)

BOOST_BITFIELD(MouseKey, 
    (LeftButton)  (0x0001)
    (RightButton) (0x0002)
    (Shift)       (0x0004)
    (Control)     (0x0008)
    (MiddleButton)(0x0010)
)
http://rsdn.nemerleweb.com
http://nemerleweb.com
Re[2]: [Trick] Делаем правильные enum'ы
От: CiViLiS Россия  
Дата: 07.09.07 18:57
Оценка:
Здравствуйте, shadone, Вы писали:

S>а реализация простая:


S>
S>      NamedEnumPair<Enum> const* pairs = typename Base_t::enum_pairs();
S>


Может я что то не понимаю, но как реализована Base_t::enum_pairs()? То есть как сопостовляется строка и енум? Кстати, не могли бы вы привести пример декларации енума.
... << RSDN@Home 1.2.0 alpha rev. 730>>
"Бог не терпит голой сингулярности" -- Роджер Пенроуз
Re[2]: Upgrage 2 (re: [Trick] Делаем правильные enum'ы)
От: Пётр Седов Россия  
Дата: 07.09.07 22:24
Оценка:
Здравствуйте, alexeiz, Вы писали:
A>
A>template <typename T, typename InternalType = int>
A>class enum_class : public T
A>{
A>    typedef typename T::type    enum_t;
A>    typedef InternalType        internal_t;
A>    ...
A>    internal_t val_;
A>};
A>

Потерялось отладочное удобство встроенного enum-а: если в MSVC6-отладчике навести курсор на enum-переменную, то отладчик покажет значение переменной в символьном виде. С Вашим power-enum-ом так легко не получится .
Пётр Седов (ушёл с RSDN)
Re[3]: Upgrage 2 (re: [Trick] Делаем правильные enum'ы)
От: alexeiz  
Дата: 08.09.07 00:28
Оценка:
Здравствуйте, Пётр Седов, Вы писали:

ПС>Потерялось отладочное удобство встроенного enum-а: если в MSVC6-отладчике навести курсор на enum-переменную, то отладчик покажет значение переменной в символьном виде. С Вашим power-enum-ом так легко не получится .


Да-с. Но если internal_t есть char, то никак не получится в принципе показать val_ в отладчике через enum_t, потому как у них разные размеры. Это можно только в случае, когда sizeof(internal_t) == sizeof(enum_t). Вот модифицированный вариант, который работает у меня в отладчике VC++ 8. Переменную смотреть в отладчике через debug_helper_.
namespace detail
{
    template <bool cond, typename T1, typename T2>
    struct if_
    {
        typedef T1 type;
    };

    template <typename T1, typename T2>
    struct if_<false, T1, T2>
    {
        typedef T2 type;
    };
}

template <typename T, typename InternalType = int>
class enum_class : public T
{
    typedef typename T::type    enum_t;
    typedef InternalType        internal_t;
    typedef typename detail::if_<sizeof(enum_t) == sizeof(internal_t), enum_t, internal_t>::type
        debug_helper_t;

public:
    enum_class(enum_t val = enum_t())
        : val_(val)
    {}

#define DEFINE_BINARY_OP(op)                            \
    bool operator op(enum_class const & other) const    \
    {                                                   \
        return val_ op other.val_;                      \
    }                                                   \

    DEFINE_BINARY_OP(==);
    DEFINE_BINARY_OP(!=);
    DEFINE_BINARY_OP(<);
    DEFINE_BINARY_OP(<=);
    DEFINE_BINARY_OP(>);
    DEFINE_BINARY_OP(>=);

#undef DEFINE_BINARY_OP

    enum_class & operator++()
    {
        ++val_;
        return *this;
    }

    enum_class operator++(int)
    {
        enum_class copy(*this);
        ++(*this);
        return copy;
    }

    enum_class & operator--()
    {
        --val_;
        return *this;
    }

    enum_class operator--(int)
    {
        enum_class copy(*this);
        --(*this);
        return copy;
    }

    enum_t get() const
    {
        return enum_t(val_);
    }

private:
    union
    {
        internal_t      val_;
        debug_helper_t  debug_helper_;
    };
};
Re[4]: [Trick] Делаем правильные enum'ы
От: Шахтер Интернет  
Дата: 08.09.07 03:47
Оценка:
Здравствуйте, Аноним, Вы писали:

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


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


M>>>Еще одна большая проблема это смешивание значений разных енумов. Значение одного енума можно присвоить по ошибке другому енуму. Собственно с этой проблемой тоже бы неплохо бороться статической типизацией.


E>>Разве так можно?
 enum E1 { E11, E12 };
E>>enum E2 { E21, E22 };
E>>E2 var = E11; // тут не компилируется вроде


А>Зато многое другое компилируется на ура.

А>У енумов проблем вагон и маленькая тележка.

Это не у enum ов. Это с руками.
В XXI век с CCore.
Копай Нео, копай -- летать научишься. © Matrix. Парадоксы
Re[4]: Сатиновые трусы -- это классно...
От: Шахтер Интернет  
Дата: 08.09.07 03:50
Оценка:
Здравствуйте, remark, Вы писали:

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


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


I>>>Интересно. А вот простая как сатиновые трусы альтернатива:


E>>Альтернатива очень хорошая. Не зря ей все пользуются.


R>Ей все пользуются от безвыходности и от безальтернативности. Тем самым признавая, что проблема есть и ей нужно хоть какое-то решение.


R>


Не от безвыходности, а от оптимальности подхода. А альтернатива в С++ есть -- ты сам одну нарисовал.
В XXI век с CCore.
Копай Нео, копай -- летать научишься. © Matrix. Парадоксы
Re[4]: Расширяемый enum
От: Шахтер Интернет  
Дата: 08.09.07 04:06
Оценка:
Здравствуйте, Erop, Вы писали:

E>Здравствуйте, Пётр Седов, Вы писали:


ПС>>Можно пример, где полезен расширяемый enum?


E>Например есть у меня класс, который поддерживает рабочие календари. И есть там enum Days { Mon, Tue, Wed, Thu, Fri }; И всё у нас хорошо.

E>Но захотелось мне это дело расширить на всю неделю, завести у класса наследника, для трудоголика, который работает и в выходные.

E>Ну это смешной пример, но если не понятно что я имею в виду, то могу вспомнить и несмешной.


Ну, можно сделать так.

template <class Int>
struct EnumBase
 {
  Int val;

  explicit EnumBase(Int val_) : val(val_) {}

  operator Int() const { return val; }
 };

struct MyEnum : EnumBase<int>
 {
  enum Type
   { 
    A=100,
    B,
    C 
   };

  explicit MyEnum(int x) : EnumBase<int>(x) {}

  MyEnum(Type x) : EnumBase<int>(x) {}
 };

struct MyEnumExt : MyEnum
 {
  enum Type
   { 
    P=200,
    Q,
    R 
   };

  explicit MyEnumExt(int x) : MyEnum(x) {}

  MyEnumExt(MyEnum::Type x) : MyEnum(x) {}

  MyEnumExt(Type x) : MyEnum(x) {}
 };
В XXI век с CCore.
Копай Нео, копай -- летать научишься. © Matrix. Парадоксы
Re[3]: [Trick] Делаем правильные enum'ы
От: shadone Норвегия  
Дата: 08.09.07 08:47
Оценка:
Здравствуйте, CiViLiS, Вы писали:

S>>а реализация простая:


S>>
S>>      NamedEnumPair<Enum> const* pairs = typename Base_t::enum_pairs();
S>>


CVL>Может я что то не понимаю, но как реализована Base_t::enum_pairs()? То есть как сопостовляется строка и енум? Кстати, не могли бы вы привести пример декларации енума.


реализовали пока так:

 namespace internal
 {
   struct MyEnumWrapper
   {
     enum Enum{a, b, c};
  
     static NamedEnumPair<Enum> const*
     enum_pairs()
     {
       static NamedEnumPair<Enum> const pairs[] =
       {
         NamedEnumPair<Enum>(a, "A"),
         NamedEnumPair<Enum>(b, "B"),
         NamedEnumPair<Enum>(c, "C")
       };
       return pairs;
     }

     static size_t
     size() { return 3; }
   };
 }
 typedef NamedEnumWrapper<Internal::MyEnumWrapper> MyNamedEnum;


теоретически можно замакросить определение enumwrapper'а, но мы не заморачивались — enum'ы пишутся обычно один раз и нечасто модифицируются. а для локализации названий enum'ов по идее можно расширить NamedEnumPair и при заполнении использовать доступ к ресурсам с помощью какого-нибудь макроса: NamedEnumPair<Enum>(a, ENUM_TR("A")); — где ENUM_TR записывает в NamedEnumPair одновременно и нелокализованное значение и локализованное, полученное из ресурсов.
Re[3]: [Trick] Делаем правильные enum'ы
От: shadone Норвегия  
Дата: 08.09.07 08:51
Оценка:
Здравствуйте, Erop, Вы писали:

S>>мы пошли еще немного дальше и каждому значению enum'а присвоили текстовое имя.


E>А мне нравится.

E>Конечно все перечисления в программе так задавать немного расточительно, да и не надо, но вот всякие интерфейсные состояния свойств -- очень даже!!!

E>Только одно замечание/предложение. ИМХО выгодно иметь ДВА имени константы. Одно на языке интерфейса программы, а другое на языке C++, первое для интерфейса и из ресурсов или откуда вы там локализованные строчки берёте, а второе для логов и из макросов, соответсвенно.

E>А так не так уж и плохо, ИМХО

в предыдущем сообщении я написал — добавить возможность использования локализованных названий enum'ов достаточно просто.

Не совсем понял про константу на языке интерфейса — само перечисление из enum'а разве не подходит в качестве названия?
а использовать действительно удобно и на клиентской стороне и на серверной чтобы выводить названия — что-то вроде
MyEnum enum = MyEnum::a;
logger << "Запрос параметра: " << enum

и автоматически выводится в лог не просто число:
"Запрос параметра: (1, А)".
Re[2]: [Trick] Делаем правильные enum'ы
От: remark Россия http://www.1024cores.net/
Дата: 10.09.07 07:22
Оценка:
Здравствуйте, shadone, Вы писали:

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


R>>Наверное многие задавались вопросом — почему сделано так странно и нелогично, почему enum'ы выносят имена своих констант в окружающее пространство имён, хотя объявлены константы вроде как внутри самого enum'а?


S>мы пошли еще немного дальше и каждому значению enum'а присвоили текстовое имя.


Я делал похожую вещь. Это уже совсем близко к:
http://www.ddj.com/cpp/184401797

Впечатление осталось немного двоякое. Т.к. реализация достаточно запутанная и нетривиальная по сравнению с простым енумом (я делал ещё более навороченный вариант с возможностью связывать тэги произвольного типа со значениями енума)
Это же максимально простой и не запутанный вариант — просто дописали пару строчек и получили кусочек синтаксического сахарку



1024cores &mdash; all about multithreading, multicore, concurrency, parallelism, lock-free algorithms
Re[3]: Upgrade
От: remark Россия http://www.1024cores.net/
Дата: 10.09.07 07:29
Оценка:
Здравствуйте, sergey_shandar, Вы писали:

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


R>>Это уже получаются даже правильные С++0х enum'ы


R>>Добавляем типизацию низлежащего типа:


_>Может делать полное описание в def, т.е.


Можно. У меня была такая идея. Осталось только добавить sfinae, что бы тип было не обязательно указывать


1024cores &mdash; all about multithreading, multicore, concurrency, parallelism, lock-free algorithms
Re[3]: Upgrade
От: remark Россия http://www.1024cores.net/
Дата: 10.09.07 07:32
Оценка:
Здравствуйте, Quasi, Вы писали:

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


R>>Это уже получаются даже правильные С++0х enum'ы


R>>Добавляем типизацию низлежащего типа:


Q>
Q>template<typename def, typename inner = typename def::type>
Q>struct right_enum : def
Q>{
Q>    typedef typename def::type type;
Q>    typedef typename inner inner; //ill-formed
Q>    inner v;
Q>    right_enum(type v) : v(static_cast<type>(v)) {} //static_cast<type>? зачем?
Q>    operator inner () const {return v;}
Q>};
Q>


Да, действительно. Последний EDG без typename не компилит. А студии пофиг. Кстати, разьве тут может быть неоднозначность.
Я думал, что здесь как при указании базовых классов неоднозначности быть не может... там же typename уже вначале написано...


1024cores &mdash; all about multithreading, multicore, concurrency, parallelism, lock-free algorithms
Re[4]: Upgrage 2 (re: [Trick] Делаем правильные enum'ы)
От: remark Россия http://www.1024cores.net/
Дата: 10.09.07 07:58
Оценка:
Здравствуйте, alexeiz, Вы писали:

A>Здравствуйте, Пётр Седов, Вы писали:


ПС>>Потерялось отладочное удобство встроенного enum-а: если в MSVC6-отладчике навести курсор на enum-переменную, то отладчик покажет значение переменной в символьном виде. С Вашим power-enum-ом так легко не получится .


A>Да-с. Но если internal_t есть char, то никак не получится в принципе показать val_ в отладчике через enum_t, потому как у них разные размеры. Это можно только в случае, когда sizeof(internal_t) == sizeof(enum_t). Вот модифицированный вариант, который работает у меня в отладчике VC++ 8.


Добавьте следующий код в файл:
Microsoft Visual Studio 8\Common7\Packages\Debugger\autoexp.dat
в секцию [Visualizer]:

right_enum<*>{
preview([(type)($e.v)])
}

и будет вам счастье


1024cores &mdash; all about multithreading, multicore, concurrency, parallelism, lock-free algorithms
Re[4]: Upgrade
От: alexeiz  
Дата: 10.09.07 08:04
Оценка:
Здравствуйте, remark, Вы писали:

R>Да, действительно. Последний EDG без typename не компилит.


Что за зверь такой этот последний EDG? Comeau что ли, или нет? Где его берут?
Re[5]: Upgrade
От: remark Россия http://www.1024cores.net/
Дата: 10.09.07 08:06
Оценка:
Здравствуйте, alexeiz, Вы писали:

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


R>>Да, действительно. Последний EDG без typename не компилит.


A>Что за зверь такой этот последний EDG? Comeau что ли, или нет? Где его берут?


http://www.edg.com/index.php?location=c_frontend

Это только frontend. Стоит денег.
Да, Comeau на фронтенде EDG.


1024cores &mdash; all about multithreading, multicore, concurrency, parallelism, lock-free algorithms
Re[2]: [Trick] Делаем правильные enum'ы
От: remark Россия http://www.1024cores.net/
Дата: 10.09.07 08:11
Оценка:
Здравствуйте, _nn_, Вы писали:

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


R>>Наверное многие задавались вопросом — почему сделано так странно и нелогично, почему enum'ы выносят имена своих констант в окружающее пространство имён, хотя объявлены константы вроде как внутри самого enum'а?


__>В Boost.Vault есть реализация вашей идеи: Boost.Enum.


Я знаю. Но это на порядок сложнее. С наворачиванием boost.pp поверх и т.д.
Я хотел сделать некий минимум действий с получанием кусочка синтаксического сахарка
Если не поленюсь, запосчу ещё свою реализацию енума с возможностью связывания произвольных тегов к значениям. Это ваще крута! Такого точно ни у кого нет!


1024cores &mdash; all about multithreading, multicore, concurrency, parallelism, lock-free algorithms
Re[6]: Upgrade
От: alexeiz  
Дата: 10.09.07 08:12
Оценка:
Здравствуйте, remark, Вы писали:

R>http://www.edg.com/index.php?location=c_frontend


R>Это только frontend. Стоит денег.


Ты хочешь сказать, что ты его купил? И потом, это же только front end. Он же ничего полезного сам по себе не делает.
Re[7]: Upgrade
От: remark Россия http://www.1024cores.net/
Дата: 10.09.07 09:16
Оценка:
Здравствуйте, alexeiz, Вы писали:

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


R>>http://www.edg.com/index.php?location=c_frontend


R>>Это только frontend. Стоит денег.


A>Ты хочешь сказать, что ты его купил? И потом, это же только front end. Он же ничего полезного сам по себе не делает.


Нет, я использую Comeau
Просто результат компиляции зависит именно от фронтенда, а что там в бекенде в данном случае совершенно не важно...



1024cores &mdash; all about multithreading, multicore, concurrency, parallelism, lock-free algorithms
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.