4

As you may know std::max and std::min "suffer" from the fact they have 1 template argument, so even simple max(container.size(), 47) will not work since .size() returns size_t and 47 is int.

I know there was historically proposal to add proper overloads to C++ but it was rejected. But from what I know it was mostly due to paper being too complex for not enough gain, so I wonder if one would use std::common_range_t as return value (invented type trait that gives you int/float big enough to hold the min/max of mixed arguments, else hard error) would that be fine...

So to finally get to my question: If we want min/max extended to take 2 template arguments as described above are there any backward compatibility or any other issues that prevent that?

note:

  • This is mostly is it technically possible question, I am not interested if WG21 plans to do anything to standardize this, mostly curious about potential technical limitations.
  • C++17 version of this question(for some reason heavily downvoted ), but more general, also deals with some other limitations.
Tony Tannous
  • 14,154
  • 10
  • 50
  • 86
NoSenseEtAl
  • 28,205
  • 28
  • 128
  • 277
  • Aren't you actually asking whether "C++ Concepts" would make it easier to implement `common_range_t` ? Do you think that `min`/`max` are somehow different from any other potential user of `common_range_t`? If so, please explain in what way they are special. – Ben Voigt May 25 '21 at 18:46
  • I don't know what you're asking. The title is talking about concepts, the content is talking about backwards compatibility of that paper. Also, I'm not sure why you think your `std::common_range_t` would differ from what's in the paper (note that some of the complexity comes from the paper predating `std::common_type`)? – Barry May 25 '21 at 18:52
  • @Barry yeah, it was clear in my head... what I meant is that common_range_t would require that types are "close enough", maybe if I used constraint in title that would be clearer? – NoSenseEtAl May 25 '21 at 18:58
  • @BenVoigt I am just curious if there is some backward comparability issue, if I have my_lib::max I can do what I want since I control all the users – NoSenseEtAl May 25 '21 at 18:59

1 Answers1

5

The two-argument std::min/max return references to the parameter that is the min/max. That requires that they be of the same type, since you can't have a function return different types. Nor can you return a reference to a temporary.

The only way to do this is to create a new function that returns a value (probably of type std::common_type), a copy of the min/max. But since it returns a copy rather than a reference, it would not be backwards compatible with std::min/max.

Nicol Bolas
  • 449,505
  • 63
  • 781
  • 982
  • "since you can't have a function return different types." that sucks, I thought that concepts will solve that ambiguity, let me godbolt that, I am saddened by this discovery... – NoSenseEtAl May 25 '21 at 19:00
  • 3
    One could presumably have the existing signature (returning a reference) and the new mixed-type one as a fallback that kicks in only when arguments fail to bind as references in the existing signature. – Ben Voigt May 25 '21 at 19:03
  • @BenVoigt I think so, issue is that common_type is not working as expected, but it is not an issue, it could be fixed by using some other type trait(I think for uint32 and int32 it return int32), or fixing a bug in my code :) https://godbolt.org/z/oMGjnz6EW – NoSenseEtAl May 25 '21 at 19:09
  • less bad godbolt example: https://godbolt.org/z/Gd7eheYas – NoSenseEtAl May 25 '21 at 19:17
  • 2
    @NoSenseEtAl: Backwards-compatibility demands one more overload to support the existing non-const reference signature, but your pattern worked great: https://godbolt.org/z/qnnsfPG1E – Ben Voigt May 25 '21 at 20:48
  • @BenVoigt cool, but std::common_type is bad for this usecase, right, it can not handle (2u,-1) case... – NoSenseEtAl May 25 '21 at 21:56
  • 1
    @NoSenseEtAl Yeah you need a template helper that really implements widening instead of simply using the C++ type promotion ranking, which thinks `int` -> `unsigned` is a widening conversion. – Ben Voigt May 25 '21 at 22:21