From 29c7ba51cdf0db9c5809a43ff6eab7e14bf21b6f Mon Sep 17 00:00:00 2001 From: Marcus Holland-Moritz Date: Thu, 23 Jun 2016 17:22:33 -0700 Subject: [PATCH] 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 --- folly/Conv.h | 18 ++++++++++++++---- folly/test/ConvTest.cpp | 10 ++++++++++ 2 files changed, 24 insertions(+), 4 deletions(-) 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]; -- 2.34.1