Re[10]: boost::lexical_cast: из std::string в enum
От: swingus  
Дата: 21.11.15 11:16
Оценка:
Здравствуйте, niXman, Вы писали:

S>>Например f0 | f1 — что выведет ваш оператор <<?

X>результатом этой операции будет интегральный тип, а не E.
X>

X>main.cxx: error: invalid conversion from 'int' to 'E' [-fpermissive]
X> E e = f0|f1;


X>к тому же, в этом случае, как выбрать нужный operator<<?


Я для битовых полей переопределяю битовую арифметику. Это удобно.

>> У вас, кстати, какое максимальное количество?

X>256

Отлично, у меня всё препроцессором генерится, поэтому из-за вложенности не хватает его возможностей. Будет время, переделаю на ваш способ.
Re[11]: boost::lexical_cast: из std::string в enum
От: niXman Ниоткуда https://github.com/niXman
Дата: 22.11.15 09:03
Оценка:
Здравствуйте, swingus, Вы писали:

S>Я для битовых полей переопределяю битовую арифметику. Это удобно.

где я могу увидеть вашу реализацию?
возможно, я бы дополнил свою реализацию, и все были бы в плюсе...
пачка бумаги А4 стОит 2000 р, в ней 500 листов. получается, лист обычной бумаги стОит дороже имперского рубля =)
Re[12]: boost::lexical_cast: из std::string в enum
От: swingus  
Дата: 23.11.15 15:06
Оценка:
Выложил код с несколькими примерами и выводом, если что-то не будет компилироваться.
Используются макросы вида PP_DEFINE/PP_ADAPT, два вида енумов и несколько их типов. Первый тип — ENUM — это то, с чем работает ваш код, второй — BITFIELD — это битовые поля, и третий — комбинация первых двух. Поясню как использовать макросы третьего типа:


enum zzz
{
  bf1 = 0x1,
  bf2 = 0x2,
  bf4 = 0x4,
  en8 = 0x8,
  en10 = 0x10,
  en18 = 0x18,
  mask = 0x18
};

PP_ADAPT_COMPLEX_ENUM
(
  zzz,
  bf1, (bf1),
  bf2, (bf2),
  bf4, (bf4),
  bf8, (bf8),
  mask, (en10, en18)
);


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


std::ostream &operator << (std::ostream &ostr, zzz en)
{
  if (bf1 == (bf1 & en)) { en &= ~bf1; ostr << "bf1 "; }
  if (bf2 == (bf2 & en)) { en &= ~bf2; ostr << "bf2 "; }
  if (bf3 == (bf3 & en)) { en &= ~bf3; ostr << "bf3 "; }
  if (bf4 == (bf4 & en)) { en &= ~bf4; ostr << "bf4 "; }

  switch (mask & en)
  {
  case en10: ostr << "en10 "; break;
  case en18: ostr << "en18 "; break;
  }
  en ~= mask;

  etc...


  return ostr;
}


Плюс есть ещё манипулятор для управления выводом.

Чего, на мой взгляд, не хватает. Лично мне не хватает количества элементов, которые можно обернуть. Затем со значительным отрывом идут отсутствие численных значений при объявлении перечисления (поэтому макрос вида PP_DEFINE_ENUM всего один), операторы ввода, какие-то compile time / runtime проверки в debug режиме (кое-какие есть, но они не тотальны, если перейти с препроцессорного метапрограммирования на шаблонное, то, думаю, ситуация улучшится), возможно, более богатое форматирование. В качестве wishful thinking можно подумать о наследуемых енумах, добавляющих новые значения к базовому типу плюс ковариантность.
В общем, если вы возьмётесь, дайте мне знать, я думаю, смогу внести свой посильный вклад.


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

X>где я могу увидеть вашу реализацию?

X>возможно, я бы дополнил свою реализацию, и все были бы в плюсе...
Re[13]: boost::lexical_cast: из std::string в enum
От: niXman Ниоткуда https://github.com/niXman
Дата: 24.11.15 11:30
Оценка:
Здравствуйте, swingus, Вы писали:

пытаюсь разобраться...
пачка бумаги А4 стОит 2000 р, в ней 500 листов. получается, лист обычной бумаги стОит дороже имперского рубля =)
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.