|
|
  |
IAR AVR 4.10A, Обойти ограничение |
|
|
|
Mar 16 2005, 15:56
|
Местный
  
Группа: Свой
Сообщений: 235
Регистрация: 9-02-05
Пользователь №: 2 526

|
Цитата(Sergio66 @ Mar 16 2005, 16:46) Как можно обойти ограничение Embedded C++ на арифметику с enum типом? Компиллятор грязно ругается на сл. строчку: current_item += i;, где current_item - enum переменная, i - int. Ругань идет даже на выражение такого типа: current_item ++; тип current_item - enum !!!
|
|
|
|
|
Mar 17 2005, 06:34
|

Adept
     
Группа: Свой
Сообщений: 3 469
Регистрация: 6-12-04
Из: Novosibirsk
Пользователь №: 1 343

|
Цитата(Sergio66 @ Mar 16 2005, 21:56) Ругань идет даже на выражение такого типа: current_item ++; тип current_item - enum !!! Вам же совершенно правильно объяснили, что так делать в С++ нельзя. Перечислимый тип - он только представление имеет в виде целого, а суть у него иная. И идея, и реализация в С++ логичны. В отличие от С, где с enum'ом можно делать что угодно - какое вообще смысл в этом перечислении в С, не понятно! А в С++ объект перечислимого типа может принимать только значения своего типа. Прямое присвоение целого и арифметика запрещены. Сами посудите: вот есть у Вас Код enum TSlon { slon = 0, slonick = 3, mamont = 5 } Slon; Теперь Вы пишете: Slon = 2; Какому значению типа TSlon оно будет соответствовать? Правильно - несущетсвующему, т.е. налицо нарушение самой идеи перечислимого типа: ведь он только для того и заведен, чтобы создать и манагить некое подмножетство целых. Те, которые не описаны в нем, это невалидные значения. И компилятор при статическом контроле типов эффективно подавляет подобные ошибки. Аналогичная ситуация и с арифметикой - результат арифметической операции может порождать значение, отсутсвующее в перечислимом типе. Единственное, что enum связывает с преобразованиями типов и целыми - это неявное преобразование значения объекта перечислимого типа в целое. Если уж очень хоцца присвоить объекту enum'а целое. то можно пользоваться насильным приведением типа: Slon = (TSlon)2; Но применение явного приведения типа означает, что "компилятор в этом случае умывает руки и говорит: "Надеюсь, парень, ты знаешь, что делаешь!" (с). И вообще, как сказал один лобастый дядька, явное приведение типа обычно указывает на ошибку этапа проектирования. Т.е. в правильно спроектированном коде необходимости в использовании явного преобразования типа не возникает. Исключения составляют всякие низкоуровеневые вещи вроде работы с аппаратурой и прочие "финты ушами". Для того они и оставлены в языке. Но это не есть красивый правильный подход во всех остальных случаях. Привычка постоянно использовать явные преобразования - источник собственноручно разложенных граблей.
--------------------
«Отыщи всему начало, и ты многое поймёшь» К. Прутков
|
|
|
|
|
Mar 17 2005, 13:59
|
Местный
  
Группа: Свой
Сообщений: 235
Регистрация: 9-02-05
Пользователь №: 2 526

|
Цитата(dxp @ Mar 17 2005, 09:34) Цитата(Sergio66 @ Mar 16 2005, 21:56) Ругань идет даже на выражение такого типа: current_item ++; тип current_item - enum !!! А в С++ объект перечислимого типа может принимать только значения своего типа. Прямое присвоение целого и арифметика запрещены. Сами посудите: вот есть у Вас Код enum TSlon { slon = 0, slonick = 3, mamont = 5 } Slon; Теперь Вы пишете: Slon = 2; Какому значению типа TSlon оно будет соответствовать? Правильно - несущетсвующему, т.е. налицо нарушение самой идеи перечислимого типа: ведь он только для того и заведен, чтобы создать и манагить некое подмножетство целых. Те, которые не описаны в нем, это невалидные значения. И компилятор при статическом контроле типов эффективно подавляет подобные ошибки. А теперь представьте задачку - (из того же примера) нужно выбрать следующее за slon значение переменной Slon. (аналогично i++). И как?
|
|
|
|
|
Mar 17 2005, 14:35
|
Местный
  
Группа: Свой
Сообщений: 235
Регистрация: 9-02-05
Пользователь №: 2 526

|
Цитата(IgorKossak @ Mar 17 2005, 17:15) Цитата(Sergio66 @ Mar 17 2005, 16:59) А теперь представьте задачку - (из того же примера) нужно выбрать следующее за slon значение переменной Slon. (аналогично i++). И как? Например, так: Код const TSlon arr[] = {slon, slonick, mamont}; и гдето в программе ... TSlon *ptr = arr; ... char myvar = *ptr++; // т. к. объект типа enum можно присваивать char, а не наоборот В моем случае это накладно. Я имею меню, где каждый пункт имеет идентификатор типа enum. Последовательность отображения пунктов меню задается их расположением (по порядку) в тексте программы, а последовательность переходов - порядком идентификаторов enum. В условиях жесточайшей экономии памяти создавать еще один массив констант, как в примере невозможно. Т.о. мне приходится иметь арифметику с типом enum. Раньше я работал с ICC. С ним было легко "договориться". Теперь - С++, но и ответственность... Вот и парюсь. Перевести весь код в IAR. Итак довольно много различий, а тут еще и такие формальные поводы вспучить мой мозг...
|
|
|
|
|
Mar 18 2005, 07:19
|

Adept
     
Группа: Свой
Сообщений: 3 469
Регистрация: 6-12-04
Из: Novosibirsk
Пользователь №: 1 343

|
Цитата(Sergio66 @ Mar 17 2005, 19:59) А теперь представьте задачку - (из того же примера) нужно выбрать следующее за 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++) и будет вам щастье  , можете мучить этот енум как заблагорассудтся. Только уже если что, не компилятор не пеняйте.  [FONT=Courier]
--------------------
«Отыщи всему начало, и ты многое поймёшь» К. Прутков
|
|
|
|
|
  |
1 чел. читают эту тему (гостей: 1, скрытых пользователей: 0)
Пользователей: 0
|
|
|