I do not think that is a particularly good example of where ternary operators should be used.
I think improving readability, simplifying flow, reducing one-shot variables, guaranteeing "good" construction, and possibly simplifying exception characteristics are the best reasons to do virtually anything.
You are free to opine that the use of the conditional operator can't do any of these things if you like. You'll just be wrong. (Any particular case may do none of these things or all of them.)
Function calls with many arguments where one or two differs based on a simple condition.
It's transformation time kiddies!
0) Let's assume there is a large number of default parameters.
Code:
base_aptr p(("magic" == derived_choice) ? (base_aptr(new derived_magic)) : (base_aptr(new derived)));
1) Let's get rid of those extra parentheses I like to use.
Code:
base_aptr p("magic" == derived_choice ? base_aptr(new derived_magic) : base_aptr(new derived));
2) A constructor is mechanically just a function call so let's make them look like a function call.
Code:
go("magic" == derived_choice ? go_derived_magic() : go_derived());
3) The string "magic" is just a magic value but let's use a magic integer value instead.
Code:
go(0 != choice ? go_derived_magic() : go_derived());
4) Now let's remove the comparison.
Code:
go(choice ? go_derived_magic() : go_derived());
5) Now let's pretend we stored the results.
Code:
go(choice ? magic_derived : derived);
6a) Let's just go ahead and offside the mechanic entirely.
Code:
go(get_something());
Would you look at that? You've hidden this possibly case specific value logic behind a probably pointless function. (I honestly find nothing wrong with such functions, but that's not the point.)
6b) Let's just offside the mechanic without changing the condition.
Code:
go(get_choice_of_derived(choice));
Would you look at that? You are copying an object. (Not every object can be copied.)
7a) Let's use a normal condition instead.
Code:
go_param_type p;
if(choice)
{
p = magic_derived;
}
else
{
p = derived;
}
go(p);
Would you look at that? You've reassigned an already constructed object. (Not every object can be reassigned.) What if the object is expensive to construct? What if reassigning the object is expensive?
7b) Let's use a pointer and delay construction.
Code:
go_param_type * p;
if(choice)
{
p = create_go_param_type_from_magic_derived(magic_derived);
}
else
{
p = create_go_param_type_from_derived(derived);
}
go(p);
Would you look at that? You've introduced a bug.
7c) Let's wrap everything to provide exception safety.
Code:
RAII_go_param_type p;
if(choice)
{
p = create_go_param_type_from_magic_derived(magic_derived);
}
else
{
p = create_go_param_type_from_derived(derived);
}
go(p.get());
Would you look a that? Sexy! Boy am I glad we didn't use the conditional operator.
For nearly everything else, an if/else statement is better.
My opinion happens to be different.
Soma