* Integral to integral
******************************************************************************/
+/**
+ * Unchecked conversion from integral to boolean. This is different from the
+ * other integral 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;
+}
+
/**
* Checked conversion from integral to integral. The checks are only
* performed when meaningful, e.g. conversion from int to long goes
template <class Tgt, class Src>
typename std::enable_if<
std::is_integral<Src>::value
- && std::is_integral<Tgt>::value
- && !std::is_same<Tgt, Src>::value,
+ && !std::is_same<Tgt, Src>::value
+ && !std::is_same<Tgt, bool>::value
+ && std::is_integral<Tgt>::value,
Tgt>::type
to(const Src & value) {
/* static */ if (std::numeric_limits<Tgt>::max()
// Test to<T>(T)
TEST(Conv, Type2Type) {
+ bool boolV = true;
+ EXPECT_EQ(to<bool>(boolV), true);
+
int intV = 42;
EXPECT_EQ(to<int>(intV), 42);
EXPECT_EQ(to<folly::StringPiece>(spV), "StringPiece");
// Rvalues
+ EXPECT_EQ(to<bool>(true), true);
EXPECT_EQ(to<int>(42), 42);
EXPECT_EQ(to<float>(4.2f), 4.2f);
EXPECT_EQ(to<double>(.42), .42);
EXPECT_EQ("foo.65", to<string>("foo.", A::z));
}
+TEST(Conv, IntegralToBool) {
+ EXPECT_FALSE(to<bool>(0));
+ EXPECT_FALSE(to<bool>(0ul));
+
+ EXPECT_TRUE(to<bool>(1));
+ EXPECT_TRUE(to<bool>(1ul));
+
+ EXPECT_TRUE(to<bool>(-42));
+ EXPECT_TRUE(to<bool>(42ul));
+}
+
template<typename Src>
void testStr2Bool() {
EXPECT_FALSE(to<bool>(Src("0")));
EXPECT_THROW(parseJson("{\"a\":1,}", off), std::runtime_error);
}
+TEST(Json, BoolConversion) {
+ EXPECT_TRUE(parseJson("42").asBool());
+}
+
TEST(Json, JavascriptSafe) {
auto badDouble = (1ll << 63ll) + 1;
dynamic badDyn = badDouble;