2

I want to know if there is a C++ function, or at least a convention for doing this:

int a = 5, b = 5, *pa = &a, *pb = &b; //These are example values if the if statement were true if( ( pa == NULL && pb == NULL ) || ( pa != NULL && pb != NULL && *pa == *pb ) ) //Do stuff 

I can improve on this a little by doing: !( ( pa == NULL ) ^ ( pb == NULL ) ) && ( !pa || *pa == *pb ) But it just seems like there should be a cleaner way of doing this.

3
  • 1
    What do you want to happen if one pointer is null but the other isn't? Commented Jan 30, 2014 at 15:07
  • They aren't equal values so the condition should be false. Commented Jan 30, 2014 at 15:08
  • There's not a better way :( Perl has a great syntax pa // NULL == pb // NULL perldoc.perl.org/perlop.html#Logical-Defined-Or Commented Jan 30, 2014 at 15:13

4 Answers 4

3

I would probably write:

if (pa == pb || (pa && pb && *pa == *pb)) 

You could get the benefit of that Perl syntax with a function template backed by a helper class that implements comparison:

template <typename T> struct Maybe { T *ptr explicit Maybe(T *ptr) : ptr(ptr) {} bool operator==(const Maybe &other) const { return (ptr == other.ptr) || (ptr && other.ptr && *ptr == *other.ptr); // or whatever other answer to this question you like } bool operator!=(const Maybe &other) const { return !(*this == other); } }; // could make it work for smart pointer types too, // but this is simple template <typename T> Maybe<T> maybe(T *ptr) { return Maybe<T>(ptr); } if (maybe(pa) == maybe(pb)) ... 

Obviously that's only worth if it you do this in a lot of different places. And to replace this one use of the Perl syntax, you could just as well have a function template that takes two pointers and returns the result...

Sign up to request clarification or add additional context in comments.

3 Comments

What if operator* is overloaded to return a random value? :-)
@KerrekSB: you can't overload operators on int* ;-) Given that the questioner proposes an alternative involving ^ I think I'm safe from operator overloads, but it may be worth noting that this isn't equivalent in the case of float because of NaNs.
@Steve Jessop I hope that your answer and the xor would be binary-equivalent. I did recognize that my original answer had a flaw !( pa ^ pb ) && ( !pa || *pa == *pb ) because ^ does not correctly handle if pa = 0x01234567 and pb = 0xFEDCBA98 because it's a bitwise operator. So mine had to be changed to: !( ( pa == NULL ) ^ ( pb == NULL ) ) && ( !pa || *pa == *pb ) All that to say yours just looks cleaner.
3

One possible simplification is:

if ( ( pa == pb ) || ( pa != NULL && pb != NULL && *pa == *pb ) ) //Do stuff 

This works because the first clause handles two cases: (i) both pa and pb are NULL or (ii) pa and pb are not NULL, but they are equal and therefore point to the same value, in which case *pa == *pb.

Comments

1

The predicate "either both pointers are null, or both pointers are non-null and the pointees are equal", could be written like this:

return pa == NULL ? pb == NULL : (pb != NULL && *pa == *pb); 

6 Comments

Generally the rule is logical operators are faster than conditional operators. So I'm trying to stay away from something like this.
@JonathanMee: whose rule is that?
@JonathanMee: That rule definitely has to go on my list.
@Steve Jessop I thought that was common knowledge. But I just timed it and if( pa == NULL ? pb == NULL : (pb != NULL && *pa == *pb) is far slower than if (pa == pb || (pa && pb && *pa == *pb)) when a and b are random, and where pa and pb are randomly NULL or pointing toward their respective values.
@JonathanMee: That may not be a fair comparison of the logical vs. conditional operators, since using pa == pb in effect optimizes for the case where pa and pb are frequently null (and hence equal) as in that case it short-circuits after a single test. What about Kerrek's code against what you started with, ( pa == NULL && pb == NULL ) || ( pa != NULL && pb != NULL && *pa == *pb )? Or my code against (pa == pb) ? true : (pa && pb && *pa == *pb).
|
0

if (pa == pb || pa && pb && *pa == *pb) // Do stuff

Comments

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.