C++: A way to declare a variable (or more than one) in an if statement that separates out the variable definition and the test?

StackOverflow https://stackoverflow.com/questions/2209875

  •  18-09-2019
  •  | 
  •  

Question

One can do this:

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

And one can do this:

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

But one cannot do:

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

Using a for statement here I think is misleading:

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

Because it looks a lot like a loop is happening - and the poor schmuck who comes after me has to decipher this garbage.

But is there no syntactic construct which combines the elegance of an if-statement that includes a local variable declaration with the ability to test its value for something other than zero?

Was it helpful?

Solution

Sometimes readability and maintainability is more important then a line of code saved.

IF you need the local variable at all then by all means introduce it explicitly in this case and maybe introduce an additional scope if you want it limited - but you should also consider if maybe you can just live with using the HIWORD macro in a couple places - this way you don't need any tricks at all.

OTHER TIPS

Preprocessor tricks:

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

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

It's ugly and certainly no better than the options you already have.

Try introducing a helper function like this:

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

Then, write your condition as:

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

That will return zero -- or, if you prefer, false -- if the first supplied value is less than the second; otherwise it returns the value. Given that it's hard to settle on the function's name, and whether it should take an inclusive or exclusive minimum, that it works here doesn't diminish it being a weird hack.

Like others have recommended, I too favor your first proposal after "And one can do this" -- the separate declaration and initialization statement followed by the conditional statement. I think that's just the natural way to do it in C++.

Tip: you could use the message cracker macros; in this way, you'd get a much shorter wndproc (without all those nested switches), your message handling code would be tidily split in separate functions (one for each message), and you almost wouldn't need all the HIWORD-LOWORD stuff, because the message-cracker macros do that for you and pass the information retrieved by lParam and wParam to you function already split in parameters.

You could modify your test a bit:

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

if you want to check if wNotifyCode > 1.

The following works for me

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

I'd hazard a guess, but don't know for sure, that the = operator has precedence over the > operator, and i know the outcome an assignment operation is the value of the assignment, the test works.

EDIT: [Putting Dunce Cap on, going to Corner]

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top