to(const Src & value) {
/* static */ if (std::numeric_limits<Tgt>::max()
< std::numeric_limits<Src>::max()) {
- FOLLY_RANGE_CHECK(value <= std::numeric_limits<Tgt>::max(),
- "Overflow");
+ FOLLY_RANGE_CHECK(
+ (!greater_than<Tgt, std::numeric_limits<Tgt>::max()>(value)),
+ "Overflow"
+ );
}
/* static */ if (std::is_signed<Src>::value &&
(!std::is_signed<Tgt>::value || sizeof(Src) > sizeof(Tgt))) {
- FOLLY_RANGE_CHECK(value >= std::numeric_limits<Tgt>::min(),
- "Negative overflow");
+ FOLLY_RANGE_CHECK(
+ (!less_than<Tgt, std::numeric_limits<Tgt>::min()>(value)),
+ "Negative overflow"
+ );
}
return static_cast<Tgt>(value);
}
#error This file may only be included from Format.h.
#endif
+#include "folly/Traits.h"
+
namespace folly {
namespace detail {
const char (&repr)[256][2]) {
// 'v >>= 7, v >>= 1' is no more than a work around to get rid of shift size
// warning when Uint = uint8_t (it's false as v >= 256 implies sizeof(v) > 1).
- for (; v >= 256; v >>= 7, v >>= 1) {
+ for (; !less_than<unsigned, 256>(v); v >>= 7, v >>= 1) {
auto b = v & 0xff;
bufLen -= 2;
buffer[bufLen] = repr[b][0];
auto& repr = formatOctal;
// 'v >>= 7, v >>= 2' is no more than a work around to get rid of shift size
// warning when Uint = uint8_t (it's false as v >= 512 implies sizeof(v) > 1).
- for (; v >= 512; v >>= 7, v >>= 2) {
+ for (; !less_than<unsigned, 512>(v); v >>= 7, v >>= 2) {
auto b = v & 0x1ff;
bufLen -= 3;
buffer[bufLen] = repr[b][0];
#define FOLLY_BASE_TRAITS_H_
#include <memory>
+#include <limits>
#include <type_traits>
#include <bits/c++config.h>
};
/*
- * Complementary type traits to check for a negative/non-positive value.
+ * Complementary type traits for integral comparisons.
*
- * `if(x < 0)` yields an error in clang for unsigned types when -Werror is used
+ * For instance, `if(x < 0)` yields an error in clang for unsigned types
+ * when -Werror is used due to -Wtautological-compare
+ *
+ *
+ * @author: Marcelo Juchem <marcelo@fb.com>
*/
namespace detail {
constexpr static bool check(T x) { return false; }
};
+template <typename RHS, RHS rhs, typename LHS>
+bool less_than_impl(
+ typename std::enable_if<
+ (rhs <= std::numeric_limits<LHS>::max()
+ && rhs >= std::numeric_limits<LHS>::min()),
+ LHS
+ >::type const lhs
+) {
+ return lhs < rhs;
+}
+
+template <typename RHS, RHS rhs, typename LHS>
+bool less_than_impl(
+ typename std::enable_if<
+ (rhs > std::numeric_limits<LHS>::max()),
+ LHS
+ >::type const
+) {
+ return true;
+}
+
+template <typename RHS, RHS rhs, typename LHS>
+bool less_than_impl(
+ typename std::enable_if<
+ (rhs < std::numeric_limits<LHS>::min()),
+ LHS
+ >::type const
+) {
+ return false;
+}
+
+template <typename LHS, LHS lhs, typename RHS>
+bool greater_than_impl(
+ typename std::enable_if<
+ (lhs <= std::numeric_limits<RHS>::max()
+ && lhs >= std::numeric_limits<RHS>::min()),
+ RHS
+ >::type const rhs
+) {
+ return lhs < rhs;
+}
+
+template <typename LHS, LHS lhs, typename RHS>
+bool greater_than_impl(
+ typename std::enable_if<
+ (lhs > std::numeric_limits<RHS>::max()),
+ RHS
+ >::type const
+) {
+ return false;
+}
+
+template <typename LHS, LHS lhs, typename RHS>
+bool greater_than_impl(
+ typename std::enable_if<
+ (lhs < std::numeric_limits<RHS>::min()),
+ RHS
+ >::type const
+) {
+ return true;
+}
+
} // namespace detail {
// same as `x < 0`
template <typename T>
constexpr bool is_non_positive(T x) { return !x || folly::is_negative(x); }
+template <typename RHS, RHS rhs, typename LHS>
+bool less_than(LHS const lhs) {
+ return detail::less_than_impl<
+ RHS, rhs, typename std::remove_reference<LHS>::type
+ >(lhs);
+}
+
+template <typename LHS, LHS lhs, typename RHS>
+bool greater_than(RHS const rhs) {
+ return detail::greater_than_impl<
+ LHS, lhs, typename std::remove_reference<RHS>::type
+ >(rhs);
+}
+
} // namespace folly
FOLLY_ASSUME_FBVECTOR_COMPATIBLE_3(std::basic_string);
* cout << "Does class Bar have a member double test(const string&, long)? "
* << boolalpha << has_test_traits<Bar, double(const string&, long)>::value;
* }
+ *
+ * @author: Marcelo Juchem <marcelo@fb.com>
*/
#define FOLLY_CREATE_HAS_MEMBER_FN_TRAITS(classname, func_name) \
template <typename, typename> class classname; \