Just exactly what operands are allowed with ?: operator

Ask about ACS, DECORATE, ZScript, or any other scripting questions here!

Moderator: GZDoom Developers

Forum rules
Before asking on how to use a ZDoom feature, read the ZDoom wiki first. If you still don't understand how to use a feature, then ask here.

Please bear in mind that the people helping you do not automatically know how much you know. You may be asked to upload your project file to look at. Don't be afraid to ask questions about what things mean, but also please be patient with the people trying to help you. (And helpers, please be patient with the person you're trying to help!)
User avatar
MartinHowe
Posts: 2041
Joined: Mon Aug 11, 2003 1:50 pm
Location: Waveney, United Kingdom

Just exactly what operands are allowed with ?: operator

Post by MartinHowe »

Everr time I try to use the ternary conditional operator, I get "Incompatible types for ?: operator". Even something simple as actor origin = (haveMaster ? master : self);. Setting up arguments for function calls is a classic way of using this operator, but if it can't handle integer based values such as actor addresses, how useful is it? Please can anyone tell me just which types it can be used with :(
User avatar
Chris
Posts: 2948
Joined: Thu Jul 17, 2003 12:07 am
Graphics Processor: ATI/AMD with Vulkan/Metal Support

Re: Just exactly what operands are allowed with ?: operator

Post by Chris »

That error message suggests the problem is master and self are two different types. The problem isn't "what types it can be used with", but that the types it is used with can't be different. In C/C++, the ?: operator would implicitly cast to a common base if they have one (following the rules about what implicit casts are allowed), and error if it couldn't get the same type for both operands (e.g. if Actor is derived from Object, and you do someBool ? someActor : someObject, the result would be an Object type as someActor can be implicitly cast to its base type; but if Actor was its own type completely separate from Object, it would be a compile error as there would be no common type). Perhaps ZScript is more strict and requires explicit casts when the two operands are different types with a common base.
User avatar
MartinHowe
Posts: 2041
Joined: Mon Aug 11, 2003 1:50 pm
Location: Waveney, United Kingdom

Re: Just exactly what operands are allowed with ?: operator

Post by MartinHowe »

Chris wrote: Tue Jun 06, 2023 11:47 pm In C/C++, the ?: operator would implicitly cast to a common base if they have one (following the rules about what implicit casts are allowed).
Thanks Chris. This is a huge fail for ZScript. Both types are descended from Actor; indeed, using the operator that way for actors is one of the main reasons we'd use it at all.

However, it's worse than this: what you describe above is formally called LSP: Liskov Substitution Principle and is fundamental to object orientated programming. The three-operand comparator in ZScript doesn't just break LSP; it throws it under the bus; it would be like having a car with everything perfect, except it doesn't have brakes :(

Do the devs have any comments before I report as a bug, please?
User avatar
Xeotroid
Posts: 442
Joined: Sat Jun 23, 2012 7:44 am
Graphics Processor: nVidia with Vulkan support
Location: Czech Rep.

Re: Just exactly what operands are allowed with ?: operator

Post by Xeotroid »

For what it's worth, the following two pieces of code work perfectly fine:

Code: Select all

bool dontLikeZombies = true;
Actor imp = Actor.Spawn("DoomImp", (0, 0, 0));
Actor zombie = Actor.Spawn("Zombieman", (0, 0, 0));
Actor enemy = dontLikeZombies ? imp : zombie;

Code: Select all

bool dontLikeZombies = true;
Actor.Spawn(dontLikeZombies ? "DoomImp" : "Zombieman", position);
So perhaps the following could work?

Code: Select all

Actor origin = haveMaster ? Actor(master) : Actor(self);
User avatar
MartinHowe
Posts: 2041
Joined: Mon Aug 11, 2003 1:50 pm
Location: Waveney, United Kingdom

Re: Just exactly what operands are allowed with ?: operator

Post by MartinHowe »

Xeotroid wrote: Thu Jun 08, 2023 6:48 am So perhaps the following could work?

Code: Select all

Actor origin = haveMaster ? Actor(master) : Actor(self);
Thanks; I would have thought so; have to look at this again when next working in that part of the code.

Return to “Scripting”