Allow unchecked conversion from floating point to bool
authorMarcus Holland-Moritz <mhx@fb.com>
Mon, 27 Jun 2016 23:39:27 +0000 (16:39 -0700)
committerFacebook Github Bot 6 <facebook-github-bot-6-bot@fb.com>
Mon, 27 Jun 2016 23:53:43 +0000 (16:53 -0700)
Summary:
In order to be consistent with integral-to-bool conversion, this
change allows conversion from floating point values to bool following
the same rule that is to be consistent with C(++) conventions. Also,
any arithmetic value can be converted to bool without potential for
undefined behaviour, so no extra checks are required.

Differential Revision: D3483760

fbshipit-source-id: 024b58d348ef679079aba4d9d5277acb46aba2a1

folly/Conv.h
folly/test/ConvTest.cpp

index 8c03e28f47f5ae4450a67fa8e7725ab433342173..871853d320b9f52893f95f8dbeb71f27c940619d 100644 (file)
@@ -83,24 +83,27 @@ to(Src && value) {
 }
 
 /*******************************************************************************
- * Integral to integral
+ * Arithmetic to boolean
  ******************************************************************************/
 
 /**
- * Unchecked conversion from integral to boolean. This is different from the
- * other integral conversions because we use the C convention of treating any
+ * Unchecked conversion from arithmetic to boolean. This is different from the
+ * other arithmetic conversions because we use the C convention of treating any
  * non-zero value as true, instead of range checking.
  */
 template <class Tgt, class Src>
 typename std::enable_if<
-  std::is_integral<Src>::value
-  && !std::is_same<Tgt, Src>::value
-  && std::is_same<Tgt, bool>::value,
-  Tgt>::type
-to(const Src & value) {
-  return value != 0;
+    std::is_arithmetic<Src>::value && !std::is_same<Tgt, Src>::value &&
+        std::is_same<Tgt, bool>::value,
+    Tgt>::type
+to(const Src& value) {
+  return value != Src();
 }
 
+/*******************************************************************************
+ * Integral to integral
+ ******************************************************************************/
+
 /**
  * Checked conversion from integral to integral. The checks are only
  * performed when meaningful, e.g. conversion from int to long goes
@@ -1220,11 +1223,11 @@ checkConversion(const Src&) {
  */
 template <class Tgt, class Src>
 typename std::enable_if<
-  (std::is_integral<Src>::value && std::is_floating_point<Tgt>::value)
-  ||
-  (std::is_floating_point<Src>::value && std::is_integral<Tgt>::value),
-  Tgt>::type
-to(const Src & value) {
+    (std::is_integral<Src>::value && std::is_floating_point<Tgt>::value) ||
+        (std::is_floating_point<Src>::value && std::is_integral<Tgt>::value &&
+         !std::is_same<Tgt, bool>::value),
+    Tgt>::type
+to(const Src& value) {
   if (detail::checkConversion<Tgt>(value)) {
     Tgt result = Tgt(value);
     if (detail::checkConversion<Src>(result)) {
index 77594c8be0d66ee0f1bd5b4f3ad10ae32d831fec..4bbca6dadd09e30759535c83d778a8942462a943 100644 (file)
@@ -840,6 +840,13 @@ TEST(Conv, BoolToFloat) {
 TEST(Conv, FloatToBool) {
   EXPECT_EQ(to<bool>(1.0), true);
   EXPECT_EQ(to<bool>(0.0), false);
+  EXPECT_EQ(to<bool>(2.7), true);
+  EXPECT_EQ(to<bool>(std::numeric_limits<double>::max()), true);
+  EXPECT_EQ(to<bool>(std::numeric_limits<double>::min()), true);
+  EXPECT_EQ(to<bool>(std::numeric_limits<double>::lowest()), true);
+  EXPECT_EQ(to<bool>(std::numeric_limits<double>::quiet_NaN()), true);
+  EXPECT_EQ(to<bool>(std::numeric_limits<double>::infinity()), true);
+  EXPECT_EQ(to<bool>(-std::numeric_limits<double>::infinity()), true);
 }
 
 TEST(Conv, NewUint64ToString) {