Commit 993de579 authored by Yedidya Feldblum's avatar Yedidya Feldblum Committed by Facebook GitHub Bot

Let some utility functions be invocable objects

Summary:
[Folly] Let some utility functions be invocable objects: `to_signed`, `to_unsigned`, `to_narrow`, `to_underlying`.

Additionally, force the template type param to be deduced.

Reviewed By: markisaa

Differential Revision: D21959729

fbshipit-source-id: eedd9f2f84efb62c99ed0d5f65123a7fe000cf0a
parent 57b8506e
...@@ -291,21 +291,29 @@ class MoveOnly { ...@@ -291,21 +291,29 @@ class MoveOnly {
using MoveOnly = moveonly_::MoveOnly; using MoveOnly = moveonly_::MoveOnly;
template <typename T> struct to_signed_fn {
constexpr auto to_signed(T const& t) -> typename std::make_signed<T>::type { template <typename..., typename T>
using S = typename std::make_signed<T>::type; constexpr auto operator()(T const& t) const noexcept ->
// note: static_cast<S>(t) would be more straightforward, but it would also be typename std::make_signed<T>::type {
// implementation-defined behavior and that is typically to be avoided; the using S = typename std::make_signed<T>::type;
// following code optimized into the same thing, though // note: static_cast<S>(t) would be more straightforward, but it would also
constexpr auto m = static_cast<T>(std::numeric_limits<S>::max()); // be implementation-defined behavior and that is typically to be avoided;
return m < t ? -static_cast<S>(~t) + S{-1} : static_cast<S>(t); // the following code optimized into the same thing, though
} constexpr auto m = static_cast<T>(std::numeric_limits<S>::max());
return m < t ? -static_cast<S>(~t) + S{-1} : static_cast<S>(t);
template <typename T> }
constexpr auto to_unsigned(T const& t) -> typename std::make_unsigned<T>::type { };
using U = typename std::make_unsigned<T>::type; FOLLY_INLINE_VARIABLE constexpr to_signed_fn to_signed;
return static_cast<U>(t);
} struct to_unsigned_fn {
template <typename..., typename T>
constexpr auto operator()(T const& t) const noexcept ->
typename std::make_unsigned<T>::type {
using U = typename std::make_unsigned<T>::type;
return static_cast<U>(t);
}
};
FOLLY_INLINE_VARIABLE constexpr to_unsigned_fn to_unsigned;
template <typename Src> template <typename Src>
class to_narrow_convertible { class to_narrow_convertible {
...@@ -356,16 +364,23 @@ class to_narrow_convertible { ...@@ -356,16 +364,23 @@ class to_narrow_convertible {
// to take advantage of the undefined-behavior sanitizer's inspection of all // to take advantage of the undefined-behavior sanitizer's inspection of all
// implicit conversions - it checks for truncation, with suppressions in place // implicit conversions - it checks for truncation, with suppressions in place
// for warnings which guard against narrowing implicit conversions. // for warnings which guard against narrowing implicit conversions.
template <typename Src> struct to_narrow_fn {
constexpr auto to_narrow(Src const& src) -> to_narrow_convertible<Src> { template <typename..., typename Src>
return to_narrow_convertible<Src>{src}; constexpr auto operator()(Src const& src) const noexcept
} -> to_narrow_convertible<Src> {
return to_narrow_convertible<Src>{src};
}
};
FOLLY_INLINE_VARIABLE constexpr to_narrow_fn to_narrow;
template <class E> struct to_underlying_fn {
constexpr std::underlying_type_t<E> to_underlying(E e) noexcept { template <typename..., class E>
static_assert(std::is_enum<E>::value, "not an enum type"); constexpr std::underlying_type_t<E> operator()(E e) const noexcept {
return static_cast<std::underlying_type_t<E>>(e); static_assert(std::is_enum<E>::value, "not an enum type");
} return static_cast<std::underlying_type_t<E>>(e);
}
};
FOLLY_INLINE_VARIABLE constexpr to_underlying_fn to_underlying;
/* /*
* FOLLY_DECLVAL(T) * FOLLY_DECLVAL(T)
......
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