Commit 5e963ae5 authored by Yedidya Feldblum's avatar Yedidya Feldblum Committed by Facebook GitHub Bot

to_integral

Summary:
A utility function for modeling explicit floating-point-to-integral conversions but without requiring the destination type to be spelled if it can be inferred from context.

Useful when it is important to highlight one abstract category of a conversion, that it is a floating-point-to-integral conversion, and when highlighting the concrete types involved tends to hide the category.

Like `to_narrow`, which models explicit integral same-sign narrowing conversions.

Differential Revision: D33992808

fbshipit-source-id: 5010d84eb6382087250a815d223ab42adfa26ca7
parent 375e7918
......@@ -465,6 +465,61 @@ struct to_narrow_fn {
};
FOLLY_INLINE_VARIABLE constexpr to_narrow_fn to_narrow{};
template <typename Src>
class to_integral_convertible {
static_assert(std::is_floating_point<Src>::value, "not a floating-point");
template <typename Dst>
static constexpr bool to_ = std::is_integral<Dst>::value;
public:
explicit constexpr to_integral_convertible(Src const& value) noexcept
: value_(value) {}
#if __cplusplus >= 201703L
explicit to_integral_convertible(to_integral_convertible const&) = default;
explicit to_integral_convertible(to_integral_convertible&&) = default;
#else
to_integral_convertible(to_integral_convertible const&) = default;
to_integral_convertible(to_integral_convertible&&) = default;
#endif
to_integral_convertible& operator=(to_integral_convertible const&) = default;
to_integral_convertible& operator=(to_integral_convertible&&) = default;
template <typename Dst, std::enable_if_t<to_<Dst>, int> = 0>
/* implicit */ constexpr operator Dst() const noexcept {
FOLLY_PUSH_WARNING
FOLLY_MSVC_DISABLE_WARNING(4244) // lossy conversion: arguments
FOLLY_MSVC_DISABLE_WARNING(4267) // lossy conversion: variables
FOLLY_GNU_DISABLE_WARNING("-Wconversion")
return value_;
FOLLY_POP_WARNING
}
private:
Src value_;
};
// to_integral
//
// A utility for performing explicit floating-point-to-integral conversion
// without specifying the destination type. Sometimes preferable to
// static_cast<Dst>(src) to document the intended semantics of the cast.
//
// Models explicit conversion with an elided destination type. Sits in between
// a stricter explicit conversion with a named destination type and a more
// lenient implicit conversion. Implemented with implicit conversion in order
// to take advantage of the undefined-behavior sanitizer's inspection of all
// implicit conversions.
struct to_integral_fn {
template <typename..., typename Src>
constexpr auto operator()(Src const& src) const noexcept
-> to_integral_convertible<Src> {
return to_integral_convertible<Src>{src};
}
};
FOLLY_INLINE_VARIABLE constexpr to_integral_fn to_integral{};
struct to_underlying_fn {
template <typename..., class E>
constexpr std::underlying_type_t<E> operator()(E e) const noexcept {
......
......@@ -173,3 +173,10 @@ TEST_F(UtilityTest, to_narrow) {
EXPECT_EQ(100, actual);
}
}
TEST_F(UtilityTest, to_integral) {
{
constexpr uint32_t actual = folly::to_integral(100.0f);
EXPECT_EQ(100, actual);
}
}
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