[C++] switch

erotic

 extern const unsigned int M;

unsigned int a;
switch (a)
{
case M:
cout << "yahoo!" << endl;
break;

default:
cout << "не yahoo блин" << endl;
}

case не компилируется: error C2051: case expression not constant
Нужели нельзя использовать extern константы?

Ivan8209

Как ты думаешь, почему си отстой?
И плюсы это --- не меняют.
---
"Аллах не ведёт людей неверных."

erotic

Тему, где ты опускаешь Си, предлагаю закрепить и сделать обязательной к прочтению
Скажи лучше, где подвох? Мне не хочется верить, что в switch действительно нельзя использовать внешним образом линкуемые константы.

Ober

Мне не хочется верить, что в switch действительно нельзя использовать внешним образом линкуемые константы.
И всякие там volatile const (без extern) тоже как бы нельзя Не знаю, как насчет C++, но в стандарте C такая тема (т.е. тема про квалификатор const) более-менее раскрыта.
Update: Но в C++, насколько я помню, с const всё немного по-другому. Смотри стандарт, в общем =)

bleyman

А головой подумать?
Свитч компилит компилятор. И компилить может очень по-разному, может табличку вставить, а может просто пару условных джампов.
Линкер компилить не умеет (как правило).

erotic

Почему компилятор не может отложить вписывание константы до момента компиляции? Может же он использовать внешним образом определенным константы в других случаях.

evgen5555

до момента компиляции?

До момента линковки.
Не может. This is by design

bleyman

Не, ну вообще в вижуал студии есть Специальная Галочка про Global Optimizations, которыми занимается именно линкер. Я так понимаю, что он может даже функции поинлайнить, если очень хочется.
Хотя со свитчом всё ещё сложнее, если, например, у тебя два кейза с экстерн константами, которые на этапе линковки оказываются одинаковыми, линкеру придётся выкидывать ошибку компиляции.
Но в данном случае скорее всего просто есть Стандарт, который на такой геморрой совершенно не рассчитан. С++ и так нифига не лёгкий для компиляции.

Ivan8209

Исторически, "const" --- указание на то, что переменную надо поместить в неизменяемую
область памяти. Если таковая есть. В остальном, если не считать невозможности прямого
присваивания, все сёвые константы являются переменными. Поэтому придуман препроцессор.
---
"Аллах не ведёт людей неверных."

Werdna

case не компилируется: error C2051: case expression not constant
Нужели нельзя использовать extern константы?
В switch надо указывать КОНКРЕТНУЮ константу. На этапе компиляции компилятор решит, какую реализацию использовать. Он может просто условный оператор поставить, может массив указателей для операторов перехода, может дерево забабахать. Всё правильно тебе написали.
Задумайся, как бы ты реализовал switch, и пойми, что в твоем случае просто непонятно какой ассеблеровский код использовать.

vall

ну никто не мешает ему в этом случает выбрать самую тупую (что-нить типа каскада if else) реализацию и забить на оптимизацию, а константы потом подставить, хотя конечно в воспитательных целях разумно заставить программиста это делать.

erotic

Ясно, всем спасибо)

bleyman

Непонятно зачем это нужно, если есть хедеры?
Вот кстати вспомнилось: какой-то шибко умный дядька из команды разработчиков .нет решил исправить такое досадное упущение C++, и сделал это самым остроумным образом: на этапе компиляции очередной ассембли компилятор засасывает значения всех константы из referenced assemblies и непосредственно использует как если б они были заданы дефайном. Проблема в том, что в дотнете-то повально используется позднее связывание, а подписывать каждую версию каждой ассембли строгим ключом всем как правило влом.
Аз э резалт: в ассембли A объявляется const int zzz = 10, компилируется ассембли Б, подставляется значение, всё отсылается клиенту. Потом разработчик что-то правит в ассембли А, в частности заменяя const int zzz = 20. Но весь интерфейс оставляет неизменным. И отсылает клиенту подправленную ассембли А. А клиентская ассембли Б продолжает считать, что zzz = 10, что может приводить к поистине удивительным результатам.

Werdna

ну никто не мешает ему в этом случает выбрать самую тупую (что-нить типа каскада if else) реализацию

Никто не мешает каскад if-else сделать ручками.
В чем прелесть switch? Да в том-то и прелесть, что это не каскад if-else.

Ivan8209

> Непонятно зачем это нужно, если есть хедеры?
Что меня постоянно радует в насильниках, так это их искренность:
они _искренне_ не понимают, почему их реализация,
сделанная в припадке отчаяния и умопомрачения, крива,
и точно так же, искренне убеждены, что так завещал АТЕТЕ,
а значит делать по-другому --- не кошерно.
---
"Аллах не ведёт людей неверных."

Ivan8209

> Никто не мешает каскад if-else сделать ручками.
Да-да, и даже убогий препроцессор не поможет.
> В чем прелесть switch?
В том, что нужно постоянно писать "break", если ты не используешь
низкоуровневых хаков.
Кроме того, все продуманные языки и даже просто языки,
способные развиваться, в конце концов ушли от switch.
Даже если сопротивлялись введению case.
switch --- это такая архаика, которая чуть ли не старше фортрана.
---
"Аллах не ведёт людей неверных."

enochka1145

Какие есть альтернативы switch?

nikita270601

Например, hashmap. Ну, или не hashmap. В общем, какой-нибудь словарь.
Ну и виртуальные методы, конечно!

Ivan8209

Хотя бы приличный case.
А ещё это делают с помощью match ещё в определении функции.
---
"Аллах не ведёт людей неверных."

Ivan8209

> Задумайся, как бы ты реализовал switch, и пойми, что в твоем случае
> просто непонятно какой ассеблеровский код использовать.
Вот что-что, а здесь очевидно, какой код использовать.
switch не обязан быть вычисляемым переходом "bra TBL(dN)".
---
"Аллах не ведёт людей неверных."

enochka1145

Что такое "приличный case"? Такой, что "break" не нужен?
Что делает match в определении функции?

Marinavo_0507

Исторически, "const" --- указание на то, что переменную надо поместить в неизменяемую
область памяти. Если таковая есть.
Видимо, C++ с историей порвал.
Вот такое компилируется:
extern int f(int);

const int a = f(1);

Ivan8209

> Что такое "приличный case"? Такой, что "break" не нужен?
Да.
Ибо так завещал великий и непогрешимый Дейкстра.
> Что делает match в определении функции?
Так удобнее определять функции:

Standard ML of New Jersey v110.42 [FLINT v1.5], October 16, 2002
- fn 0 => 1 | _ => 0;
val it = fn : int -> int

---
"Аллах не ведёт людей неверных."

tamusyav

Вот такое компилируется:

extern int f(int);

const int a = f(1);
Конечно. А чего тут криминального?
Оставить комментарий
Имя или ник:
Комментарий: