From: Marcus Holland-Moritz Date: Fri, 24 Jun 2016 00:22:33 +0000 (-0700) Subject: Fix conversion from bool to floating point value X-Git-Tag: 2016.07.26~126 X-Git-Url: http://demsky.eecs.uci.edu/git/?a=commitdiff_plain;h=29c7ba51cdf0db9c5809a43ff6eab7e14bf21b6f;p=folly.git Fix conversion from bool to floating point value Summary: Due to the definition of how floating point values convert to boolean, the check for undefined behaviour wouldn't work correctly. The result of (1 - 0.9999999999999999) would yield 0 when converted to an integer, but yields true (1) when converted to a boolean. As all floating point values can thus be converted to boolean without triggering undefined behaviour, this change overloads checkConversion() appropriately Reviewed By: yfeldblum Differential Revision: D3477368 fbshipit-source-id: 5b2aeb6194629cf3a6195529aac2362c0d35799c --- diff --git a/folly/Conv.h b/folly/Conv.h index c0a350fe..53be6b82 100644 --- a/folly/Conv.h +++ b/folly/Conv.h @@ -1163,10 +1163,11 @@ namespace detail { * integer value without triggering undefined behaviour. */ template -typename std::enable_if< - std::is_floating_point::value && std::is_integral::value, +inline typename std::enable_if< + std::is_floating_point::value && std::is_integral::value && + !std::is_same::value, bool>::type -inline checkConversion(const Src& value) { +checkConversion(const Src& value) { constexpr Src tgtMaxAsSrc = static_cast(std::numeric_limits::max()); constexpr Src tgtMinAsSrc = static_cast(std::numeric_limits::min()); if (value >= tgtMaxAsSrc) { @@ -1193,13 +1194,22 @@ inline checkConversion(const Src& value) { // Integers can always safely be converted to floating point values template -typename std::enable_if< +constexpr typename std::enable_if< std::is_integral::value && std::is_floating_point::value, bool>::type checkConversion(const Src&) { return true; } +// Also, floating point values can always be safely converted to bool +// Per the standard, any floating point value that is not zero will yield true +template +constexpr typename std::enable_if< + std::is_floating_point::value && std::is_same::value, + bool>::type +checkConversion(const Src&) { + return true; +} } /** diff --git a/folly/test/ConvTest.cpp b/folly/test/ConvTest.cpp index a14eeb28..cbf7510a 100644 --- a/folly/test/ConvTest.cpp +++ b/folly/test/ConvTest.cpp @@ -823,6 +823,16 @@ TEST(Conv, IntToFloat) { #endif } +TEST(Conv, BoolToFloat) { + EXPECT_EQ(to(true), 1.0); + EXPECT_EQ(to(false), 0.0); +} + +TEST(Conv, FloatToBool) { + EXPECT_EQ(to(1.0), true); + EXPECT_EQ(to(0.0), false); +} + TEST(Conv, NewUint64ToString) { char buf[21];