2

There is interesting note on C++ reference for first overload of std::clamp(one that does not take custom comparator).

Uses operator< (until C++20) std::less<> (since C++20) to compare the values.

All I found on cppreference is this (about std::less), but that seems borderline useless motivation since "most" (all) implementations know how to compare pointers.

A specialization of std::less for any pointer type yields the implementation-defined strict total order, even if the built-in < operator does not.

Barry
  • 286,269
  • 29
  • 621
  • 977
NoSenseEtAl
  • 28,205
  • 28
  • 128
  • 277
  • "implementations know how to compare pointers" no they don't, they (at least gcc) perform some optimizations that assume that you only ever compare pointers into the same object with `<`. – Marc Glisse Jul 14 '21 at 20:23
  • Implementations know how to compare pointers, and that knowledge is embedded in `std::less`. It may be simpler to compare pointers to elements within an array than to compare unrelated pointers, on some architectures. When you want to compare unrelated pointers you must use `std::less` so the implementation knows it has to do the extra work, if applicable. – François Andrieux Jul 14 '21 at 20:25
  • 1
    It's tightening the specification slightly - which has been a trend in recent C++ standards (e.g. changing previously undefined or unspecified behaviour to be implementation-defined). When comparing two unrelated pointers (that are not part the same object) behaviour of `<` is unspecified but behaviour of `std::less` is implementation-defined. Roughly speaking, implementation-defined (standard specifies constraints, and the implementation must document the choice) is considered preferable to unspecified (implementation can do what it likes within constraints). – Peter Jul 14 '21 at 20:26
  • On comparing Pointers: "_...Many implementations also provide strict total ordering of pointers of random origin, e.g. if they are implemented as addresses within continuous virtual address space. Those implementations that do not (e.g. where not all bits of the pointer are part of a memory address and have to be ignored for comparison, or an additional calculation is required or otherwise pointer and integer is not a 1 to 1 relationship), provide a specialization of std::less for pointers that has that guarantee...."_ https://en.cppreference.com/w/cpp/language/pointer – Richard Critten Jul 14 '21 at 21:43

1 Answers1

1

This is just a wording clarification, it doesn't change any of the meaning of the algorithm.

Barry
  • 286,269
  • 29
  • 621
  • 977
  • but isn't std::less legal customization point? although you should probably just define < properly... – NoSenseEtAl Jul 14 '21 at 20:25
  • @NoSenseEtAl It's legal. [Cppreference](https://en.cppreference.com/w/cpp/utility/functional/less) doesn't say it's not, and says *"Unless specialized [does X]"*. – HolyBlackCat Jul 14 '21 at 20:31
  • 1
    @NoSenseEtAl It's not using `std::less`, it's using `std::less`. – Barry Jul 14 '21 at 21:13
  • @Barry thank you, I would just upvote the comment normally, but I accidentally flagedi ti :/ so I can not upvote it.. – NoSenseEtAl Jul 14 '21 at 21:21
  • Using the Operator < ist different from using std::less<> in principle, and offen enough in practice. Thus, Not Just a cosmetic Change. If you want to Claim so, Look at all commits changing anThing there, and also consider the comment could be wrong. – Deduplicator Jul 14 '21 at 21:31
  • 1
    @Deduplicator Huh? `std::less<>{}(x, y)` always evaluates as `x < y`. – Barry Jul 14 '21 at 21:34
  • 1
    Does it? For pointers, it seems to be a full ordering consistent with std::less, instead of the partial order < gives. Whether those are the same for some Implementations is immaterial. – Deduplicator Jul 15 '21 at 13:46
  • @Barry maybe Deduplicator is right, this is what cpp reference says: The function call operator yields the implementation-defined strict total order over pointers if the < operator between arguments invokes a built-in comparison operator for a pointer, even if the built-in < operator does not. https://en.cppreference.com/w/cpp/utility/functional/less_void Some days I really hate C++ more than the others, I can not believe I am discussing if < and std::less are same for pointers :) – NoSenseEtAl Jul 15 '21 at 14:55
  • @Deduplicator You can approach this two ways. EITHER you can say that `T*` just doesn't meet the precondition of `Cpp17LessThanComparable` because pointers don't have a strict weak order, so it's UB for all pointers. OR you can say that `T*` only has to meet the precondition for the domain of values passed in - in which case `<` and `std::less` mean the same thing in the case where we meet the precondition. Either way, on the defined domain of the function, there's no difference. – Barry Jul 15 '21 at 16:20
  • ... so it was unspecified for pointers not to or behind parts of the same object. If it was meant to or not, this change broadened the domain of std::clamp. As an aside, the added parts of the domain are irrelevant to anyone AFAICS. – Deduplicator Jul 15 '21 at 22:21
  • @Deduplicator This change did not broaden the domain of `std::clamp` - the domain is defined by the precondition, which did not change. – Barry Jul 15 '21 at 22:50
  • https://github.com/cplusplus/draft/blob/4bb0543c314c7b302b185245e18e6e0e577b1d72/source/algorithms.tex#L8582 If the bounds point to the same object, but the value to a completely Independent one, before the Change that would have been obviously Bad. Now, the result is well-defined... – Deduplicator Jul 16 '21 at 08:26
  • @Deduplicator No, it's not well-defined. The [precondition](https://eel.is/c++draft/alg.clamp#2) would still rule out that case. – Barry Jul 16 '21 at 19:29