Перейти к содержанию
    

IAR AVR 4.10A

Как можно обойти ограничение Embedded C++ на арифметику с enum типом?

Компиллятор грязно ругается на сл. строчку:

current_item += i;, где current_item - enum переменная, i - int.

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Диапазон представления типа int в общем случае шире enum типа, поэтому претензии компилятора вполне обоснованы.

Обойти ограничения можно приведением типа или подавлением данного диагностического сообщения, но это не элегантный выход.

Гораздо лучше изменить программу так, чтобы стилистически, с точки зрения типов, было всё верно.

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Как можно обойти ограничение Embedded C++ на арифметику с enum типом?

Компиллятор грязно ругается на сл. строчку:

current_item += i;, где current_item - enum переменная, i - int.

 

Ругань идет даже на выражение такого типа: current_item ++; тип current_item - enum !!!

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Ругань идет даже на выражение такого типа: current_item ++; тип current_item - enum !!!

Вам же совершенно правильно объяснили, что так делать в С++ нельзя. Перечислимый тип - он только представление имеет в виде целого, а суть у него иная. И идея, и реализация в С++ логичны. В отличие от С, где с enum'ом можно делать что угодно - какое вообще смысл в этом перечислении в С, не понятно!

 

А в С++ объект перечислимого типа может принимать только значения своего типа. Прямое присвоение целого и арифметика запрещены. Сами посудите: вот есть у Вас

 

enum TSlon
{
   slon    = 0,
   slonick = 3,
   mamont  = 5
} Slon;

 

Теперь Вы пишете: Slon = 2; Какому значению типа TSlon оно будет соответствовать? Правильно - несущетсвующему, т.е. налицо нарушение самой идеи перечислимого типа: ведь он только для того и заведен, чтобы создать и манагить некое подмножетство целых. Те, которые не описаны в нем, это невалидные значения. И компилятор при статическом контроле типов эффективно подавляет подобные ошибки.

 

Аналогичная ситуация и с арифметикой - результат арифметической операции может порождать значение, отсутсвующее в перечислимом типе.

 

Единственное, что enum связывает с преобразованиями типов и целыми - это неявное преобразование значения объекта перечислимого типа в целое.

 

Если уж очень хоцца присвоить объекту enum'а целое. то можно пользоваться насильным приведением типа: Slon = (TSlon)2; Но применение явного приведения типа означает, что "компилятор в этом случае умывает руки и говорит: "Надеюсь, парень, ты знаешь, что делаешь!" (с). И вообще, как сказал один лобастый дядька, явное приведение типа обычно указывает на ошибку этапа проектирования. Т.е. в правильно спроектированном коде необходимости в использовании явного преобразования типа не возникает. Исключения составляют всякие низкоуровеневые вещи вроде работы с аппаратурой и прочие "финты ушами". Для того они и оставлены в языке. Но это не есть красивый правильный подход во всех остальных случаях. Привычка постоянно использовать явные преобразования - источник собственноручно разложенных граблей.

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Ругань идет даже на выражение такого типа: current_item ++; тип current_item - enum !!!

 

А в С++ объект перечислимого типа может принимать только значения своего типа. Прямое присвоение целого и арифметика запрещены. Сами посудите: вот есть у Вас

 

enum TSlon
{
   slon    = 0,
   slonick = 3,
   mamont  = 5
} Slon;

 

Теперь Вы пишете: Slon = 2; Какому значению типа TSlon оно будет соответствовать? Правильно - несущетсвующему, т.е. налицо нарушение самой идеи перечислимого типа: ведь он только для того и заведен, чтобы создать и манагить некое подмножетство целых. Те, которые не описаны в нем, это невалидные значения. И компилятор при статическом контроле типов эффективно подавляет подобные ошибки.

 

 

А теперь представьте задачку - (из того же примера) нужно выбрать следующее за slon значение переменной Slon. (аналогично i++). И как?

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

А теперь представьте задачку - (из того же примера) нужно выбрать следующее за slon значение переменной Slon. (аналогично i++). И как?

Например, так:

const TSlon arr[] = {slon, slonick, mamont};
и гдето в программе ...
   TSlon *ptr = arr;
...
   char myvar = *ptr++;   // т. к. объект типа enum можно присваивать char, а не наоборот

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

А теперь представьте задачку - (из того же примера) нужно выбрать следующее за slon значение переменной Slon. (аналогично i++). И как?

Например, так:

const TSlon arr[] = {slon, slonick, mamont};
и гдето в программе ...
   TSlon *ptr = arr;
...
   char myvar = *ptr++;   // т. к. объект типа enum можно присваивать char, а не наоборот

 

В моем случае это накладно. Я имею меню, где каждый пункт имеет идентификатор типа enum. Последовательность отображения пунктов меню задается их расположением (по порядку) в тексте программы, а последовательность переходов - порядком идентификаторов enum. В условиях жесточайшей экономии памяти создавать еще один массив констант, как в примере невозможно. Т.о. мне приходится иметь арифметику с типом enum. Раньше я работал с ICC. С ним было легко "договориться". Теперь - С++, но и ответственность... Вот и парюсь. Перевести весь код в IAR. Итак довольно много различий, а тут еще и такие формальные поводы вспучить мой мозг...

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

А теперь представьте задачку - (из того же примера) нужно выбрать следующее за slon значение переменной Slon. (аналогично i++). И как?

 

У Вас типичная ошибка этапа проектирования: Вы неправильно выбрали тип для реализации требуемой Вам функциональности. enum тут не подходит.

 

Если Вам нужно просто целое, то и используйте его. Если Вам не нравится, то целое - голое, без "обвески", то приделайте обвеску - напишите класс. Типа:

 

class TSlon
{
public:
   TSlon() : Value(0)       { }
   TSlon(int x) : Value(x) { }
   TSlon(const TSlon& x) : Value(x) { }
   void Increase() { Value++; if(Value > MAX_VAL) Value = 0; } // wrap around
   void Decrease() { Value--; if(Value < 0) Value = MAX_VAL; } // wrap around }
   void operator ++() { Increase(); }
   void operator --() { Decrease(); }
   operator int() { return Value; }
   ... // остальной интерфейс, если он требуется

private:
   int Value;
}

 

Тут у вас будет максимум и там, и там. И производительность максимальная, и безопасность использования. Вообще-то, С++ для этого и придуман - чтобы сочетать скорость С с безопасностью и удобством более высокоуровевых языков.

 

P.S. Вообще-то, интерфейсы с меню не так пишутся. Там удобно использовать иерархию полиморфных классов и виртуальные функции. Получается удобно, быстро, безопасно и расширяемо.

 

P.P.S. И ничего не мешает делать так, как делали на прежнем пакете - включите С режим (не используйте ключи --ec++/--eec++) и будет вам щастье :), можете мучить этот енум как заблагорассудтся. Только уже если что, не компилятор не пеняйте. :)

 

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Здесь была длинная и ненужная цитата. В следующий раз будет предупреждение

Все верно, только при разработке проекта 2 года назад был выбран компиллятор ICC. Теперь остается только облизываться на прелести С++; Переписывать 20 000 строк под С++ никакой бюджет не выдержит :))

Изменено пользователем IgorKossak

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Присоединяйтесь к обсуждению

Вы можете написать сейчас и зарегистрироваться позже. Если у вас есть аккаунт, авторизуйтесь, чтобы опубликовать от имени своего аккаунта.

Гость
Ответить в этой теме...

×   Вставлено с форматированием.   Вставить как обычный текст

  Разрешено использовать не более 75 эмодзи.

×   Ваша ссылка была автоматически встроена.   Отображать как обычную ссылку

×   Ваш предыдущий контент был восстановлен.   Очистить редактор

×   Вы не можете вставлять изображения напрямую. Загружайте или вставляйте изображения по ссылке.

×
×
  • Создать...