Jaanus
Jaanus

Reputation: 16541

C++ "OR" operator

can this be done somehow?

if((a || b) == 0) return 1;
return 0;

so its like...if a OR b equals zero, then...but it is not working for me. my real code is:

bool Circle2::contains(Line2 l) {
    if((p1.distanceFrom(l.p1) || p1.distanceFrom(l.p2)) <= r) {
        return 1;
    }
    return 0;
}

Upvotes: 5

Views: 77701

Answers (10)

Mr. Man
Mr. Man

Reputation: 3

As you seem to know, in C++, 0 is false and 1 is true. With that in mind, to answer your first question (Code 1):

return !(a && b);

If one of the bools is false then a && b is false so !(a && b) is true i.e., 1, otherwise both a and b are true so a && b is true so !(a && b) is false i.e., 0. You can also do (Code 2)

return !a || !b;

but this performs up to three logical operations whereas the first one performs up to two, which is less. The equivalence of these two expressions is one of De Morgan's laws.

To fix your second code (Code 3):

bool Circle2::contains(Line2 l) {
    return p1.distanceFrom(l.p1) <= r || p1.distanceFrom(l.p2) <= r;
}

If you want to avoid the double <= r (Code 4):

bool Circle2::contains(Line2 l) {
    for (auto p : { l.p1, l.p2 }) {
        if (p1.distanceFrom(p) <= r) {
            return true;
        }
    }
    return false;
};

The for loop initializes an anonymous array of two values, l.p1 and l.p2, and checks each one and returns true immediately if it finds a satisfying point. That means that it short-circuits, like ||. false is only returned after both points were found not to satisfy. I would recommend using something like Code 3 because two points to check is simple enough to do with a simple || expression. In an alternate scenario where you had to check a lot of points, something like Code 4 would be useful.

Upvotes: 0

user unknown
user unknown

Reputation: 36239

If you have lot of that code, you may consider a helping method:

bool distanceLE (Point p1, Point p2, double threshold) {
    return (p1.distanceFrom (p2) <= threshold)
}

bool Circle2::contains (Line2 l) {
    return distanceLE (p1, l.p1, r) && distanceLE (p1, l.p2, r);
}

If you sometimes have <, sometimes <=, >, >= and so on, maybe you should pass the operator too, in form of a function.

In some cases your intentions by writing this:

if ((a || b) == 0) return 1;
return 0;

could be expressed with an bitwise-or:

if ((a | b) == 0) return 1;
return 0;

and simplified to

return  ! (a | b);

But read up on bitwise operations and test it carefully. I use them rarely and especially I didn't use C++ for some time.

Note, that you inverted the meaning between your examples 1 and 2, returning true and false in the opposite way.

And bitwise less-equal doesn't make any sense, of course. :)

Upvotes: 1

Marlon
Marlon

Reputation: 20312

Fun with templates:

template <typename T>
struct or_t
{
  or_t(const T& a, const T& b) : value1(a), value2(b)
  {
  }

  bool operator==(const T& c)
  {
    return value1 == c || value2 == c;
  }

private:
  const T& value1;
  const T& value2;
};

template <typename T>
or_t<T> or(const T& a, const T& b)
{
  return or_t<T>(a, b);
}

In use:

int main(int argc, char** argv)
{
  int a = 7;
  int b = 9;

  if (or(a, b) == 7)
  {
  }

  return 0;
}

It performs the same comparison you would normally do, though, but at your convenience.

Upvotes: 2

tpdi
tpdi

Reputation: 35151

The C++ language specifies that the operands of || ("or") be boolean expressions.

If p1.distanceFrom(l.p1) is not boolean (that is, if distanceFrom returns int, or double, or some numeric class type), the compiler will attempt to convert it to boolean.

For built in numeric type, the conversion is: non-zero converts to true, zero converts to false. If the type of p1.distanceFrom(l.p1) is of class type Foo, the compiler will call one (and only one) user defined conversion, e.g., Foo::operator bool(), to convert the expression's value to bool.

Upvotes: 2

Rao
Rao

Reputation: 892

You have to specify the condition separately each time:

if (a == 0) || (b == 0))
    bla bla;

When you do

if ((a || b) == 0)
    bla bla;

it has a different meaning: (a || b) means "if either a or b is non-zero (ie. true), then the result of this expression is true". So when you do (a||b) == 0, you are checking if the result of the previously explained expression is equal to zero (or false).

Upvotes: 2

KyleWpppd
KyleWpppd

Reputation: 2030

C++ isn't that smart. You have to do each comparison manually.

bool Circle2::contains(Line2 l) {
if((p1.distanceFrom(l.p1) <= r) || (p1.distanceFrom(l.p2) <= r)) return 1;
    return 0;
}

Upvotes: 0

Jim Lewis
Jim Lewis

Reputation: 45105

I think you really want something like this:

bool Circle2::contains(Line2 l) {
if((p1.distanceFrom(l.p1) <= r) || (p1.distanceFrom(l.p2) <= r)) return 1;
    return 0;
}

Upvotes: 1

helium
helium

Reputation: 1078

Your condition should be (a == 0 || b == 0) or (p1.distanceFrom(l.p1) <= r || p1.distanceFrom(l.p2)) <= r)

Upvotes: 0

Cat Plus Plus
Cat Plus Plus

Reputation: 129854

C++ doesn't support any construct like that. Use if (a == 0 || b == 0).

Upvotes: 0

CodesInChaos
CodesInChaos

Reputation: 108820

You need to write the full expression:

(a==0)||(b==0)

And in the second code:

if((p1.distanceFrom(l.p1)<= r) || (p1.distanceFrom(l.p2)<=r) )
    return 1;

If you do ((a || b) == 0) this means "Is the logical or of a and b equal to 0. And that's not what you want here.

And as a side note: the if (BooleanExpression)return true; else return false pattern can be shortened to return BooleanExpression;

Upvotes: 20

Related Questions