dhein
dhein

Reputation: 6555

Is there a way of doing a "post switch" like operation with bool?

I have a condition like the following where I just want to have the second bool be the trigger for a single time, since this condition is invoked relatively often I don't like the idea of doing the assignment of it being false every time the condition is true so, I tried to take advantage of the order of logical AND and OR and the post increment operator. But it appears to work don't do what I expected it to do. So is there a way to make a post state switch for this line?

where firstTitleNotSet is:

bool firstTitleNotSet;

if (titleChangedSinceLastGet() || (p_firstTitleNotSet && p_firstTitleNotSet++))

The idea is that the first part is the primary trigger and the second is the trigger that only has to trigger the first time.

While I easily could do

if (titleChangedSinceLastGet() || p_firstTitleNotSet)
{
    firstTitleNotSet = false;
    //...
}

I don't like this as it is reassigning false when ever the conditional block is invoked.

So is there some way of "post change" the value of a bool from true to false? I know that this would work the other way around but this would negate the advantage of the method most time being the true trigger and therefor skipping the following check.

Note: The reasons for me making such considerations isntead of just taking the second case is, that this block will be called frequently so I'm looking to optimize its consumed runtime.

Upvotes: 1

Views: 102

Answers (4)

SirGuy
SirGuy

Reputation: 10770

A more readable way than the assignment inside a ternary operator inside an or inside an if would be just moving the operations to their own statements:

    bool needsUpdate = titleChangedSinceLastGet();
    if(!needsUpdate && firstTitleSet)
    {
        needsUpdate = true;
        firstTitleSet = false;
    }

    if(needsUpdate)
    {
        //...
    }

This is likely to produce very similar assembly than the less readable alternative proposed since ternary operators are mostly just syntactic sugar around if statements.

To demonstrate this I gave GCC Explorer the following code:

extern bool first; bool changed();

int f1()
{
  if (changed() ||
     (first ? ((first=false), true):false))
    return 1;
  return 0;
}

int f2()
{
  bool b = changed();
  if(!b && first)
  {
    b = true;
    first = false;
  }
  return b;
}

and the generated assembly had only small differences in the generated assembly after optimizations. Certainly have a look for yourself.

I maintain, however, that this is highly unlikely to make a noticeable difference in performance and that this is more for interest's sake.
In my opinion:

    if(titleChangedSinceLastUpdate() || firstTitleSet)
    {
        firstTitleSet = false;
        //...
    }

is an (at least) equally good option.

You can compare the assembly of the above functions with this one to compare further.

bool f3()
{
  if(changed() || first)
  {
    first = false;
    return true;
  }
  return false;
}

Upvotes: 1

Ohad Eytan
Ohad Eytan

Reputation: 8464

That should work:

int firstTitleSet = 0;
if (titleChangedSinceLastGet() || (!firstTitleSet++))

If you wish to avoid overflow you can do:

int b = 1;
if (titleChangedSinceLastGet() || (b=b*2%4))

at the first iteration b=2 while b=0 at the rest of them.

Upvotes: 0

Josh Sanford
Josh Sanford

Reputation: 672

In this kind of situation, I usually write:

bool firstTitleNotSet = true;

if (titleChangedSinceLastGet() || firstTitleNotSet)
{
    if (firstTileNotSet) firstTitleNotSet = false;
    //...
}

That second comparison will likely be optimized by the compiler.

But if you have a preference for a post-increment operator:

int iterationCount = 0;
if (titleChangedSinceLastGet() || iterationCount++ != 0) 
{
    //...
}

Note that this will be a problem if iterationCount overflows, but the same is true of the bool firstTitleNotSet that you were post-incrementing.

In terms of code readability and maintainability, I would recommend the former. If the logic of your code is sound, you can probably rely on the compiler to do a very good job optimizing it, even if it looks inelegant to you.

Upvotes: 0

Sam Varshavchik
Sam Varshavchik

Reputation: 118320

Well, you could do something like:

if (titleChangedSinceLastGet() ||
    (p_firstTitleNotSet ? ((p_firstTitleNotSet=false), true):false))

An alternative syntax would be:

if (titleChangedSinceLastGet() ||
    (p_firstTitleNotSet && ((p_firstTitleNotSet=false), true)))

Either one looks somewhat ugly. Note, however, that this is NOT the same as your other alternative:

if (titleChangedSinceLastGet() || p_firstTitleNotSet)
{
    p_firstTitleNotSet = false;
    //...
}

With your proposed alternative, pontificate the fact that p_firstTitleNotSet gets reset to false no matter what, even if the conditional was entered because titleChangedSinceLastGet().

Upvotes: 2

Related Questions