C ++: способ объявить переменную (или более одного) в операторе if, который разделяет определение переменной и тест? - PullRequest
4 голосов
/ 05 февраля 2010

Можно сделать это:

case WM_COMMAND:
if (WORD wNotifyCode = HIWORD(wparam))
{
  ...
}

И можно сделать это:

case WM_COMMAND:
{
  WORD wNotifyCode = HIWORD(wparam);
  if (wNotifyCode > 1) {
    ...
  }
}

Но никто не может сделать:

case WM_COMMAND:
if ((WORD wNotifyCode = HIWORD(wparam)) > 1)
{
  ...
}

Использование выражения for здесь, я думаю, вводит в заблуждение:

case WM_COMMAND:
for (WORD wNotifyCode = HIWORD(wparam); wNotifyCode > 1; wNotifyCode = 0)
{
  ...
}

Потому что похоже, что происходит петля - и бедняга, идущий за мной, должен расшифровать этот мусор.

Но нет ли синтаксической конструкции, которая сочетает в себе элегантность оператора if, который включает в себя объявление локальной переменной, с возможностью проверки ее значения на предмет чего-то отличного от нуля?

Ответы [ 6 ]

3 голосов
/ 05 февраля 2010

Иногда удобочитаемость и удобство сопровождения важнее, чем сохраненная строка кода.

ЕСЛИ вам вообще нужна локальная переменная, то в любом случае, в любом случае, введите ее явно и, возможно, добавьте дополнительную область, если вы хотите ее ограничить, - но вы также должны подумать, можете ли вы просто жить с использованием макроса HIWORD в нескольких местах - таким образом, вам не нужны никакие уловки.

1 голос
/ 06 февраля 2010

Совет: вы можете использовать макросы взломщика сообщений; таким образом, вы получите намного более короткий wndproc (без всех этих вложенных ключей), ваш код обработки сообщений будет аккуратно разделен на отдельные функции (по одной для каждого сообщения), и вам почти не понадобятся все HIWORD-LOWORD такие вещи, потому что макросы взломщика сообщений делают это за вас и передают информацию, полученную с помощью lParam и wParam, в функцию, уже разделенную на параметры.

1 голос
/ 05 февраля 2010

Попробуйте ввести вспомогательную функцию следующим образом:

template <typename T>
T zeroIfLess(T val, T base)
{
  return val < base ? T(0) : val;
}

Затем напишите ваше состояние как:

if (WORD wNotifyCode = zeroIfLess(HIWORD(wparam), 2))

Это вернет ноль - или, если вы предпочитаете, false - если первое предоставленное значение меньше второго; в противном случае он возвращает значение. Принимая во внимание, что трудно определить имя функции, а также то, должна ли она работать с включающим или исключительным минимумом, то, что она работает здесь, не умаляет ее как странного хака.

Как и другие рекомендовали, я тоже предпочитаю ваше первое предложение после «И это можно сделать» - отдельное заявление о декларации и инициализации, за которым следует условное утверждение. Я думаю, что это просто естественный способ сделать это в C ++.

1 голос
/ 05 февраля 2010

Трюки препроцессора:

#define IF_2(init, test) \
    for (bool first_ = true; first_;) for (init; first_ && (test); first_ = false)

IF_2(WORD wNotifyCode = HIWORD(wparam), wNotifyCode > 1)
{
  ...
}

Это некрасиво и, конечно, не лучше тех вариантов, которые у вас уже есть.

0 голосов
/ 05 февраля 2010

у меня работает следующее

if (WORD nNotifyCode = HIWORD(test) > 1)
{
}

Я бы рискнул предположить, но точно не знаю, что оператор = имеет приоритет над оператором>, и я знаю, что результат операции присваивания является значением присваивания, тест работает.

EDIT: [Надевает шапку Дансе, идет в Уголок]

0 голосов
/ 05 февраля 2010

Вы можете немного изменить свой тест:

if (WORD wNotifyCode = HIWORD(wparam) - 1)

, если вы хотите проверить, если wNotifyCode > 1.

...