3

Inspired by the current top answer to this popular question concerning getting the larger of two values in C#.

Consider a function that accepts two integer pointers, and returns a pointer. Both pointers might be nullptr.

const int*  max(const int* a, const int* b);

If a or b is a nullptr return the non-null pointer. If both are nullptr, return nullptr.

If both are valid pointers return max(*a, *b);.

The currently most upvoted answer for the C# question is

int? c = a > b ? a ?? b : b ?? a;

int? represents a nullable value, not unlike a pointer.

How can this be expressed in an elegant and idiomatic fashion in c++?

My immediate attempt was along the lines of

const int* maxp(const int* a, const int* b){
   if (!a) return b;
   if (!b) return a;
   return &std::max(*a, *b); 
}
Community
  • 1
  • 1
Captain Giraffe
  • 14,407
  • 6
  • 39
  • 67
  • 4
    No problem with temporaries here, `std::max` returns a reference to the bigger element. I consider your code *vastly* superior to any unreadable `?:` operator hack. – Baum mit Augen May 01 '15 at 21:39
  • 2
    `std::optional` is (will be) a better match for `Nullable`, and it supports the same things. `auto c = b < a ? a.value_or(b) : b.value_or(a);` should do it unless I missed something. – chris May 01 '15 at 21:41

2 Answers2

2

The temptation of the ternary operator is big

const int* maxp(const int *a, const int *b) {
    return a? (b? &std::max(*a, *b) : a) : b;
}

but it's because it's funny, not because it's better.

The code in the question is more readable.

6502
  • 112,025
  • 15
  • 165
  • 265
-2

There is problem with your code, which is that it is returning a pointer to the output of std::max. Taking the address of the output of a function is usually buggy, and always in poor taste. It is only correct if the function returns a reference to a variable that will persist as long as the pointer is held.

I would replace the last line of your function with a simple if statement:

if (*a > *b) return a;
else return b;

This way you will always return one of the pointers that were the input to your function.

P.S. I have glanced at the standard regarding std::max, and had trouble understanding it. But ultimately, even if your code does work (because std::max returns a reference), it is better not to take the address of said reference.

P.P.S. Avoiding the ternary operator is by far best in terms of clarity here. The rest of your function is fine.

David Roundy
  • 1,706
  • 2
  • 14
  • 20