4

I have a doubt in the following scenario (C++):

Say, I have an if condition

if ( a ? b ? c : d : false)
{
    // do something
}
else
{
    // do something else
}

This is my interpretation of how it works:

If a is true, it checks b. Then,
    - If b is true, the if loop is reduced to if (c)
    - If b is false, the if loop is reduced to if (d)
If a is false, the if loop is reduced to if (false)

Is my understanding correct?
Is using this better or multiple if/else checks?

Grijesh Chauhan
  • 57,103
  • 20
  • 141
  • 208
mdv
  • 499
  • 2
  • 8
  • 14

5 Answers5

8

Please use this in parenthesis, as it helps improve readability. Also, it is fine using multiple ternary operators.

if ( a ? (b ? c : d) : false)
{
    // do something
}
else
{
    // do something else
}
Manikandan Sigamani
  • 1,964
  • 1
  • 15
  • 28
  • @mdv:The order of execution changes. But it will give you the end result u need. – Manikandan Sigamani Sep 26 '13 at 05:40
  • Say my check "a" is a pointer validity check, and in "b" I check a data pointed by the pointer. I need to check "b" only if "a" is true, that is, if the pointer is valid. In this case, the order becomes important. How will the code behave with no parenthesis? – mdv Sep 26 '13 at 05:42
  • 2
    The execution order does not change. `?:` only evaluates one of the 2nd and 3rd operands, based on the 1st. So the parentheses do not change execution order, just improve readability. – Angew is no longer proud of SO Sep 26 '13 at 06:25
6

Your question is in two parts, firstly about the behavior of the statement, and then about whether you should do this; allow me to show you how many programmers would solve the second.

Imagine it's 4.30am on a Saturday morning and you're hung over and there is a bug in this code, and you need it fixed within the next 30 minutes or your job/business is at risk.

if (a ? b ? c : d : false)

or

if (a) {
    if (b)
        return c;
    else
        return d;
} else {
    return false;
}

or

if (!a)
    return false;
if (!b)
    return d;
return c;

or

if (a)
    return b ? c : d;
else
    return false;

Which was the right choice?

-- edit --

With single letter variable names, it looks innocent enough. So, some real variable names:

if (application.config.usingUTCTimezone ? system.environment.biosTimezoneIsUTC ? haveNTPServerConfigured : system.time.clockIsSynchronized : false)

or

if (application.config.usingUTCTimezone ?
    system.environment.biosTimezoneIsUTC ?
        haveNTPServerConfigured : system.time.clockIsSynchronized
    : false)

or

if (application.config.usingUTCTimezone) {
    if (system.environment.biosTimezoneIsUTC)
        return haveNTPServerConfigured;
    else
        return system.time.clockIsSynchronized;
} else {
    return false;
}

or

if (!application.config.usingUTCTimezone)
    return false;
if (!system.environment.biosTimezoneIsUTC)
    return system.time.clockIsSynchronized;
return haveNTPServerConfigured;

or

if (application.config.usingUTCTimezone)
    return system.environment.biosTimezoneIsUTC ? haveNTPServerConfigured : system.time.clockIsSynchronized;
else
    return false;
kfsone
  • 23,617
  • 2
  • 42
  • 74
  • 3
    Yes! Clarity over brevity. – john Sep 26 '13 at 07:31
  • 1
    Uh, other than the first option being the worst, I'm not sure which of the other three are best? Or is your point that any of the latter are better? – aquirdturtle Jul 08 '19 at 21:39
  • 1
    seems like the last option is the clear and concise, readability and performance should be higher priorities than minimizing lines of code – Federico Dec 17 '20 at 23:24
  • @Federico I added samples with real variable names for contrast. Annecdote: golang tackles this by not having the ternary but instead letting you use 'switch' with conditionals producing a rather nice and readable alternative. – kfsone Dec 19 '20 at 00:53
3

Is my understanding correct?

Yes, your interpretation is correct.

Is using this better or multiple if/else checks?

As you know the code:

if ( a ? b ? c : d : false)
{
   "Code-1"
}
else
{
   "Code-2"
}

could be written like:

if(a){  
  if(b){
    if (c){
       "code-1"
    }
    else{
       "code-2"       
    }
  }
  else{
    if(d){
       "code-1"
    }
    else{
       "code-2"
    }
  }
}
else{  
   //then false;       
    "Code-2"
}

Now which you will prefer in above two. Second is long and includes many nested level code (hard to understand and bug). Additionally first code that can be improved in readability as:

if ( a ? (b ? c : d) : false) 

as @ManikandanSigamani answered.

As I noted @WhozCraig also give an another technique to write your code better if (a && (b ? c : d)) using && that supports Short-Circuit logic.

A good programmer is one who know one than one technique to solve a problem and also know which is better. A short and linear codding is preferable in general. In small writing small code chances of making mistakes are less (looks like functional programming better then imperative programming). And small code easily can improved as in your case suggested by @ManikandanSigamani and @WhozCraig.

I will prefer: if (a && (b ? c : d)) form!

Grijesh Chauhan
  • 57,103
  • 20
  • 141
  • 208
1

Yes, you are correct at stating:

If a is true, it checks b. Then,
    - If b is true, the if condition is reduced to if (c)
    - If b is false, the if condition is reduced to if (d)
If a is false, the if condition is reduced to if (false)

but if() is not a loop but a condition statement. and writing condition in parenthesis make it more readable.

if ( a ? (b ? c : d) : false)

or you can simplify it:

if ( a && (b ? c : d))
Zaheer Ahmed
  • 28,160
  • 11
  • 74
  • 110
0

Though it works, nesting ternary operator like this is seldom readable.

Writing it as

if ( a && (( b && c ) || d )) {
  // do something
} else {
  // do something else
}

is, imho, much more readable and it is not much longer than your original code.

Adrian Shum
  • 38,812
  • 10
  • 83
  • 131