Commit 29c7ba51 authored by Marcus Holland-Moritz's avatar Marcus Holland-Moritz Committed by Facebook Github Bot 7

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
parent 1186ac53
...@@ -1163,10 +1163,11 @@ namespace detail { ...@@ -1163,10 +1163,11 @@ namespace detail {
* integer value without triggering undefined behaviour. * integer value without triggering undefined behaviour.
*/ */
template <typename Tgt, typename Src> template <typename Tgt, typename Src>
typename std::enable_if< inline typename std::enable_if<
std::is_floating_point<Src>::value && std::is_integral<Tgt>::value, std::is_floating_point<Src>::value && std::is_integral<Tgt>::value &&
!std::is_same<Tgt, bool>::value,
bool>::type bool>::type
inline checkConversion(const Src& value) { checkConversion(const Src& value) {
constexpr Src tgtMaxAsSrc = static_cast<Src>(std::numeric_limits<Tgt>::max()); constexpr Src tgtMaxAsSrc = static_cast<Src>(std::numeric_limits<Tgt>::max());
constexpr Src tgtMinAsSrc = static_cast<Src>(std::numeric_limits<Tgt>::min()); constexpr Src tgtMinAsSrc = static_cast<Src>(std::numeric_limits<Tgt>::min());
if (value >= tgtMaxAsSrc) { if (value >= tgtMaxAsSrc) {
...@@ -1193,13 +1194,22 @@ inline checkConversion(const Src& value) { ...@@ -1193,13 +1194,22 @@ inline checkConversion(const Src& value) {
// Integers can always safely be converted to floating point values // Integers can always safely be converted to floating point values
template <typename Tgt, typename Src> template <typename Tgt, typename Src>
typename std::enable_if< constexpr typename std::enable_if<
std::is_integral<Src>::value && std::is_floating_point<Tgt>::value, std::is_integral<Src>::value && std::is_floating_point<Tgt>::value,
bool>::type bool>::type
checkConversion(const Src&) { checkConversion(const Src&) {
return true; 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 <typename Tgt, typename Src>
constexpr typename std::enable_if<
std::is_floating_point<Src>::value && std::is_same<Tgt, bool>::value,
bool>::type
checkConversion(const Src&) {
return true;
}
} }
/** /**
......
...@@ -823,6 +823,16 @@ TEST(Conv, IntToFloat) { ...@@ -823,6 +823,16 @@ TEST(Conv, IntToFloat) {
#endif #endif
} }
TEST(Conv, BoolToFloat) {
EXPECT_EQ(to<double>(true), 1.0);
EXPECT_EQ(to<double>(false), 0.0);
}
TEST(Conv, FloatToBool) {
EXPECT_EQ(to<bool>(1.0), true);
EXPECT_EQ(to<bool>(0.0), false);
}
TEST(Conv, NewUint64ToString) { TEST(Conv, NewUint64ToString) {
char buf[21]; char buf[21];
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment