О синтаксическом сахаре

Есть у меня некий варез и в этом варезе настраивается клавиатурная раскладка (т.е. каждому действию можно сопоставить произвольный клавиатурный аккорд).

В потрохах редактора раскладок содержится примерно такой вот код (по смыслу):

// Инициализация
QKeySequence key; // Текущий shortcut
QPushButton *keybutton = new QPushButton(key.toStrin());
keybutton->setProperty("shortcut",key.toString());
..
// Обработка нажатой кнопки в слоте, который зовется по нажатию:
QObject *sender = QObject::sender();
QString shortcut = sender->property("shortcut").toString(); // Какую кнопку на самом деле нажали
И все работало прекрасно, пока я не решил сделать в этом же месте еще и обработку кнопок мыши, чтобы действие можно было бы назначить и на, к примеру, Ctrl-Shift-RightClick.

Меняем код немножко:

My_KeyOrMouse key; // My_KeyOrMouse - generic-контейнер для QKeySequence или мышиных событий
QPushButton *keybutton = new QPushButton(key.toString()); // Строковое представление есть
keybutton->setProperty("shortcut",key.toString());
..
// Обработка нажатой кнопки в слоте, который зовется по нажатию:
QObject *sender = QObject::sender();
QString shortcut = sender->property("shortcut").toString();
И тут начинаются чудеса: для кнопок все продолжает работать, а для мышиных кнопок - нет, sender->property(..).toString(); возвращает пустую строку.

Разгадка оказалась проста:

Если посмотреть в sender->property("shortcut").type() то выяснится, что тип - вовсе даже QKeySequence. И, да, такая пропертя есть у QAbstractButton (а я об этом узнал 10 минут назад, написав эту самую строчку с type())

То есть получилось так, что я использовал (чисто случайно) уже готовую проперть известного типа и названия. Дальше чудом получилось так, что я инициализировал ее такой строкой, которая нормально конвертировалась в родной для этой проперти тип (потому что все строки были вида Ctrl+Alt+A). Дальше property() возвращала мне объект, для которого определана toString().

Как сайд-эффект я получил то, что кнопки реагировали на "свои" хоткеи - я этого не хотел, оно получилось само.

Естественно, как только в это место полезли строки произвольного вида (Ctrl+Alt+RClick) - они конвертироваться в QKeySequence перестали и для этих строк все поломалось.

Ну и вылечилось потом сменой названия проперти на (произвольную) другую строку - отчего эта новая проперть получила желаемый тип QString по первой инициализации.

Вот сижу я и думаю думу:

  • С одной стороны, я приветствую невероятной сладости синтаксический сахар, который дал мне QVariant и система динамических пропертей (если свойства нет - оно создается, если есть - используется то что есть). Все работало и даже приятными сайд-эффектами с хоткеями.
  • С другой стороны, как только я мимо этого сахара промахнулся - я получил компилируемое и с виду работающее приложение, вот только пропертя терялись.
То есть я бы, наверное, предпочел бы сахару поменьше, да.

Comments

а оно тебе об этом на stderr не вопило что ли об ошибке?

Нет, ни в qDebug()/qWarning(), ни в stderr.

А о чем ему орать? У QKeySequence вполне валидно делать ее из QString, ну получился No_Key или как там правильно, в чем ошибка?

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

Какой же это синтаксический сахар? Это как раз его отсутствие. И проблемы оттуда же.

Это его наличие в чистом виде. Мне из QString прозрачно сделали QKeySequence, потом обратно, почти как в языках без типизации.

Синтаксис где?

Так автоконверсия типов во все стороны.

Я всю жизнь считал, что автоконверсия типов -- это нифига не синтаксис.

Синтаксис -- это то, что бы разбираем грамматикой, LALR там, или Recursive Descent или что у вашего компилятора внутри. Та часть языка, которая не меняется самим языком (окей, оставим в стороне true macros, которые есть в некоторых языках и которые позволяют менять именно синтаксис языка, это явно не про C/C++ даже с QT-обвеской).

Операторы -- синтаксис. for -- синтаксический сахар (потому что он пишется через while и избыточен в этом смысле, можно без него, но с ним симпатичнее, а средства языка не позволяют сделать его вручную из while, верёвки и палки).

А вот эта автоконверсия -- это нифига не синтаксис вообще ни разу. Это самая что нинаетсь семантика.

Ну почему ж.
Автоконверсия типов - это замена для object->convert_to_type()

Сладкий невидимый сахар.