Reformulate constexpr_min and constexpr_max to achieve stability in sorting as descri...
authorEric Niebler <eniebler@fb.com>
Mon, 5 Dec 2016 20:51:19 +0000 (12:51 -0800)
committerFacebook Github Bot <facebook-github-bot-bot@fb.com>
Mon, 5 Dec 2016 20:53:31 +0000 (12:53 -0800)
Summary: There is a famous long-standing "bug" in the standard library regarding the semantics of min and max wrt values that are equivalent wrt op< but not equal. Let's not make the same mistake with constexpr_min and constexpr_max.

Reviewed By: yfeldblum, luciang, Orvid, ot

Differential Revision: D4269635

fbshipit-source-id: 19b464c949dc0cf07afb08eaf657ae8b242ca42d

folly/portability/Constexpr.h

index 16b6458fab1b59ac9ed118ec35eb3c2ff2131686..dc21a7d36d1662eecf29c929017c6cadae8ec17b 100755 (executable)
 
 namespace folly {
 
+// TLDR: Prefer using operator< for ordering. And when
+// a and b are equivalent objects, we return b to make
+// sorting stable.
+// See http://stepanovpapers.com/notes.pdf for details.
 template <typename T>
 constexpr T constexpr_max(T a, T b) {
-  return a > b ? a : b;
+  return b < a ? a : b;
 }
 
+// When a and b are equivalent objects, we return a to
+// make sorting stable.
 template <typename T>
 constexpr T constexpr_min(T a, T b) {
-  return a < b ? a : b;
+  return b < a ? b : a;
 }
 
 namespace detail {
@@ -67,7 +73,7 @@ struct constexpr_abs_helper<
     return t < static_cast<T>(0) ? -t : t;
   }
 };
-}
+} // namespace detail
 
 template <typename T>
 constexpr auto constexpr_abs(T t)