реклама на сайте
подробности

 
 
> enum в С++, как определить неявное преобразование одного enum к другому?
Сергей Борщ
сообщение Jan 26 2007, 18:55
Сообщение #1


Гуру
******

Группа: Модераторы
Сообщений: 8 455
Регистрация: 15-05-06
Из: Рига, Латвия
Пользователь №: 17 095



задача в следующем:
Код
enum command_t {CMD1, CMD2, CMD3 };
enum device1_cmd {CMD4 = CMD3, CMD5, CMD6};
enum device2_cmd {CMD7 = CMD3, CMD8, CMD9};
т.е. есть некий общий набор команд и его расширения специфичные для разных устройств.
Теперь если я пытаюсь сделать
device1_cmd = CMD9;
то получаю ошибку a value of type "device2_cmd" cannot be used to initialize an entity of type "device1_cmd". Что правильно, и ради этого все enum и затевались.
но такую же ошибку я получаю и на
device1_cmd = CMD1;
а вот этого не хочется. Т.е. хочется объявить оператор неявного преобразования из command_t в device1_cmd. Как это сделать?

P.S. явное преобразование не хочется потому что можно случайно преобразовать совсем не то, что нужно.


--------------------
На любой вопрос даю любой ответ
"Write code that is guaranteed to work, not code that doesn’t seem to break" (C++ FAQ)
Go to the top of the page
 
+Quote Post
 
Start new topic
Ответов
v_shamaev
сообщение Jan 26 2007, 19:20
Сообщение #2


Местный
***

Группа: Свой
Сообщений: 304
Регистрация: 5-07-04
Из: г. Москва
Пользователь №: 259



Цитата(Сергей Борщ @ Jan 26 2007, 18:55) *
Теперь если я пытаюсь сделать
device1_cmd = CMD9;
то получаю ошибку a value of type "device2_cmd" cannot be used to initialize an entity of type "device1_cmd". Что правильно, и ради этого все enum и затевались.


Это же название типа, а не имя переменной. Определите переменную типа device1_cmd, а уж ей присваивайте значение


--------------------
Водку пьянствовать и безобразия нарушать!!!
Go to the top of the page
 
+Quote Post
Сергей Борщ
сообщение Jan 26 2007, 22:14
Сообщение #3


Гуру
******

Группа: Модераторы
Сообщений: 8 455
Регистрация: 15-05-06
Из: Рига, Латвия
Пользователь №: 17 095



Цитата(v_shamaev @ Jan 26 2007, 18:20) *
Цитата(Сергей Борщ @ Jan 26 2007, 18:55) *

device1_cmd = CMD9;

Это же название типа, а не имя переменной. Определите переменную типа device1_cmd, а уж ей присваивайте значение
Извиняюсь, кончно же у меня что-то вроде
Код
device1_cmd cmd1;
cmd1 = CMD5;    // проходит, ибо "родное"
cmd1 = CMD9;    // не проходит, и правильно
cmd1 = CMD1;    // не проходит, а я хочу чтоб проходило.
Вопрос - как сделать так, чтобы значение типа command_t неявно(!) при необходимости преобразовывалось к device1_cmd. С классами понятно - добавил конструктор и все. А как с enum?

Цитата(zltigo @ Jan 26 2007, 19:30) *
Код
aaaa = (device1_cmd)CMD1;

По идее должно работать
Да, работает. Но меня это не устраивает. Для чего заводится enum? Чтобы ненароком не присвоить переменной значение которого она никогда не может иметь. Ошибка отлавливается компилятором и сразу. Если я делаю приведение типов вручную, компилятор уже ничего не проверяет. Он пропустит и
Код
aaaa = (device1_cmd)CMD9;
а я хочу этого избежать.


--------------------
На любой вопрос даю любой ответ
"Write code that is guaranteed to work, not code that doesn’t seem to break" (C++ FAQ)
Go to the top of the page
 
+Quote Post
Olej
сообщение Jan 27 2007, 14:09
Сообщение #4


Местный
***

Группа: Свой
Сообщений: 351
Регистрация: 11-09-05
Из: Харьков
Пользователь №: 8 458



Цитата(Сергей Борщ @ Jan 26 2007, 23:14) *
Код
device1_cmd cmd1;
cmd1 = CMD5;    // проходит, ибо "родное"
cmd1 = CMD9;    // не проходит, и правильно
cmd1 = CMD1;    // не проходит, а я хочу чтоб проходило.
Вопрос - как сделать так, чтобы значение типа command_t неявно(!) при необходимости преобразовывалось к device1_cmd.


А как вам понравится такое "проходит"
Код
#include <iostream>
using std::cout;
using std::endl;

enum command_t { CMD1, CMD2, CMD3 = 3 };
enum device1_cmd { CMD4 = CMD3, CMD5 = 8, CMD6 = 12 };
enum device2_cmd { CMD7 = CMD3, CMD8, CMD9 };

int main( int argc, char* argv[] ) {
   device1_cmd cmd1;
   cmd1 = CMD5;    // проходит, ибо "родное"
   cmd1 = device1_cmd( CMD4 | CMD5 );
   cout << cmd1 << endl;
   exit( EXIT_SUCCESS );
};

и чтоб не быть голословным - вот вам прогон (gcc 3.3.5 - QNX 6.3.2):
Код
/root/enum # enum
11


Вы хотите использовать enum совсем не в том качестве, для которого они предназначены: enum фактически не вводит нового класса, а всего лишь определяет синоним, но за счёт именной (а не структурной) типизации С++, между ними запрещены преобразования (но не запрещено присвоить "хрен знает что", что и делается в примере выше). Именно из-за этого вы не можете (и не сможете) переопределить операцию "=" - эта операция должна определяться как член класса (внутри класса) - а класса то нет? ohmy.gif smile.gif
P.S. специально не отвечал вчера - засомневался smile.gif , решил перепровериться у Страуструпа - у него утверждается в точности то же самое.

Тем более, нереалистично желание переложить контроль допустимости значений на компилятор (как я понял, вы хотели бы чтоб это были проверки времени компиляции а не времени исолнения): значение, которое вы захотите присваивать может динамически измениться на выполнении (как в примере) - кто тогда будет проверять его допустимость?

Цитата(Сергей Борщ @ Jan 26 2007, 23:14) *
С классами понятно - добавил конструктор и все. А как с enum?


Вот и определите то что вы хотите внутри класса (вложив внутрь класса) ... определите для него "=" ... но и тут будут проблемы - ну и что вы будуте делать когда выясниться что присваивается недопустимое значение?

P.S. предполагаю (чутьё подсказывает smile.gif ) - что то что вы хотите вы могли бы определить используя template ... в стиле a'la Александреску smile.gif ...
Попробуйте.
Go to the top of the page
 
+Quote Post
Сергей Борщ
сообщение Jan 27 2007, 18:02
Сообщение #5


Гуру
******

Группа: Модераторы
Сообщений: 8 455
Регистрация: 15-05-06
Из: Рига, Латвия
Пользователь №: 17 095



Цитата(Olej @ Jan 27 2007, 13:09) *
А как вам понравится такое "проходит"
Код
   cmd1 = device1_cmd( CMD4 | CMD5 );

Так ведь это явное приведение. Против этого я и не протестую smile.gif
Цитата(Olej @ Jan 27 2007, 13:09) *
Вы хотите использовать enum совсем не в том качестве, для которого они предназначены
спасибо за подробное объяснение. Кажется, проясняется.

Цитата(Olej @ Jan 27 2007, 13:09) *
Тем более, нереалистично желание переложить контроль допустимости значений на компилятор (как я понял, вы хотели бы чтоб это были проверки времени компиляции а не времени исолнения): значение, которое вы захотите присваивать может динамически измениться на выполнении (как в примере) - кто тогда будет проверять его допустимость?
Ну почему же нереалистично? Для классов реалистично "и тут хочу!". А во время исполнения сдуру можно все что угодно через указатели привести и никакой компилятор не спасет.
Цитата(Olej @ Jan 27 2007, 13:09) *
Цитата(Сергей Борщ @ Jan 26 2007, 23:14) *

С классами понятно - добавил конструктор и все. А как с enum?

Вот и определите то что вы хотите внутри класса (вложив внутрь класса) ... определите для него "=" ...
Видимо так и придется. Только если я помещу enum внутрь класса, то мне придется постоянно писать command_t::CMD1, а это несколько утомительно и опять же требует помнить какие команды описаны в каком классе. Ладно, буду городить класс.

Цитата(Olej @ Jan 27 2007, 13:09) *
P.S. предполагаю (чутьё подсказывает smile.gif ) - что то что вы хотите вы могли бы определить используя template ... в стиле a'la Александреску smile.gif ...
Попробуйте.
Кто такой Александреску? Можно пример его стиля?


--------------------
На любой вопрос даю любой ответ
"Write code that is guaranteed to work, not code that doesn’t seem to break" (C++ FAQ)
Go to the top of the page
 
+Quote Post
Olej
сообщение Jan 27 2007, 22:07
Сообщение #6


Местный
***

Группа: Свой
Сообщений: 351
Регистрация: 11-09-05
Из: Харьков
Пользователь №: 8 458



Цитата(Сергей Борщ @ Jan 27 2007, 19:02) *
Цитата(Olej @ Jan 27 2007, 13:09) *

А как вам понравится такое "проходит"
Код
   cmd1 = device1_cmd( CMD4 | CMD5 );

Так ведь это явное приведение. Против этого я и не протестую smile.gif

Да, но явное приведение того, что приводится не должно ни в каком случае: среди допустимых значений перечисления device1_cmd - не допускается и не предусмотрено значение 11! (только: CMD4 = 3,
CMD5 = 8, CMD6 = 12 - что такое 11 ?).

Цитата(Сергей Борщ @ Jan 27 2007, 19:02) *
Ну почему же нереалистично? Для классов реалистично "и тут хочу!". А во время исполнения сдуру можно все что угодно через указатели привести и никакой компилятор не спасет.

Именно поэтому допустимость приведения (присвоения) нужно контролировать на фазе исполнения, а не компиляции.

Цитата(Сергей Борщ @ Jan 27 2007, 19:02) *
Видимо так и придется. Только если я помещу enum внутрь класса, то мне придется постоянно писать command_t::CMD1, а это несколько утомительно и опять же требует помнить какие команды описаны в каком классе. Ладно, буду городить класс.

Не обязательно оперировать сложными именами типа command_t::CMD1 - вы можете #define определить внутренние имена как простые внешние, так весь QNX переопределён.
P.S. может вам покажется полезным кое-что о трюках QNX, которые можно перенести в другие окружения, посмотреть здесь:
http://qnxclub.net/modules.php?name=Forums...ewforum&f=7

Цитата(Сергей Борщ @ Jan 27 2007, 19:02) *
Кто такой Александреску? Можно пример его стиля?

Андрей Александреску "Современное проектирование на С++" Пер. с англ. - М. : Издательский дом "Вильямс", 2002. - 336 стр.
Много обсуждаемая книжка: одни принимают с восторгом, другия ругаются брызгая слюной wink.gif.
Go to the top of the page
 
+Quote Post



Reply to this topicStart new topic
1 чел. читают эту тему (гостей: 1, скрытых пользователей: 0)
Пользователей: 0

 


RSS Текстовая версия Сейчас: 18th July 2025 - 01:03
Рейтинг@Mail.ru


Страница сгенерированна за 0.01457 секунд с 7
ELECTRONIX ©2004-2016