Skip to content

Commit

Permalink
Add to_underlying_type to cast enum to underlying (facebook#1028)
Browse files Browse the repository at this point in the history
Summary:
- It is verbose at the call sites to cast an enum or enum class to its
  underlying type.
- Introduce `to_underlying_type`, which, given an enum or enum class,
  returns the value from static casting to the underlying type.
Pull Request resolved: facebook#1028

Reviewed By: stevegury

Differential Revision: D14199619

Pulled By: yfeldblum

fbshipit-source-id: fde85b9be50945a390b18ba1448a0137f3d7b63e
  • Loading branch information
JoeLoser authored and sandraiser committed Mar 4, 2019
1 parent 501802d commit e73e5c7
Show file tree
Hide file tree
Showing 4 changed files with 15 additions and 10 deletions.
12 changes: 5 additions & 7 deletions folly/Conv.h
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,7 @@
#include <folly/Range.h>
#include <folly/Traits.h>
#include <folly/Unit.h>
#include <folly/Utility.h>
#include <folly/lang/Exception.h>
#include <folly/lang/Pretty.h>
#include <folly/portability/Math.h>
Expand Down Expand Up @@ -648,15 +649,13 @@ template <class Tgt, class Src>
typename std::enable_if<
std::is_enum<Src>::value && IsSomeString<Tgt>::value>::type
toAppend(Src value, Tgt* result) {
toAppend(
static_cast<typename std::underlying_type<Src>::type>(value), result);
toAppend(to_underlying_type(value), result);
}

template <class Src>
typename std::enable_if<std::is_enum<Src>::value, size_t>::type
estimateSpaceNeeded(Src value) {
return estimateSpaceNeeded(
static_cast<typename std::underlying_type<Src>::type>(value));
return estimateSpaceNeeded(to_underlying_type(value));
}

/*******************************************************************************
Expand Down Expand Up @@ -1547,8 +1546,7 @@ typename std::enable_if<
!std::is_convertible<Tgt, StringPiece>::value,
Expected<Tgt, ConversionCode>>::type
tryTo(const Src& value) {
using I = typename std::underlying_type<Src>::type;
return tryTo<Tgt>(static_cast<I>(value));
return tryTo<Tgt>(to_underlying_type(value));
}

template <class Tgt, class Src>
Expand All @@ -1567,7 +1565,7 @@ typename std::enable_if<
!std::is_convertible<Tgt, StringPiece>::value,
Tgt>::type
to(const Src& value) {
return to<Tgt>(static_cast<typename std::underlying_type<Src>::type>(value));
return to<Tgt>(to_underlying_type(value));
}

template <class Tgt, class Src>
Expand Down
4 changes: 2 additions & 2 deletions folly/DynamicConverter.h
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@
#include <folly/Likely.h>
#include <folly/Optional.h>
#include <folly/Traits.h>
#include <folly/Utility.h>
#include <folly/dynamic.h>
#include <folly/lang/Exception.h>

Expand Down Expand Up @@ -334,8 +335,7 @@ struct DynamicConstructor<
C,
typename std::enable_if<std::is_enum<C>::value>::type> {
static dynamic construct(const C& x) {
using type = typename std::underlying_type<C>::type;
return dynamic(static_cast<type>(x));
return dynamic(to_underlying_type(x));
}
};

Expand Down
7 changes: 7 additions & 0 deletions folly/Utility.h
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@
#include <utility>

#include <folly/CPortability.h>
#include <folly/Portability.h>
#include <folly/Traits.h>

namespace folly {
Expand Down Expand Up @@ -299,4 +300,10 @@ constexpr auto to_unsigned(T const& t) -> typename std::make_unsigned<T>::type {
return static_cast<U>(t);
}

template <class E>
constexpr std::underlying_type_t<E> to_underlying_type(E e) noexcept {
static_assert(std::is_enum<E>::value, "not an enum type");
return static_cast<std::underlying_type_t<E>>(e);
}

} // namespace folly
2 changes: 1 addition & 1 deletion folly/hash/Hash.h
Original file line number Diff line number Diff line change
Expand Up @@ -506,7 +506,7 @@ struct IsAvalanchingHasher<hasher<std::string>, K> : std::true_type {};
template <typename T>
struct hasher<T, std::enable_if_t<std::is_enum<T>::value>> {
size_t operator()(T key) const noexcept {
return Hash()(static_cast<std::underlying_type_t<T>>(key));
return Hash()(to_underlying_type(key));
}
};

Expand Down

0 comments on commit e73e5c7

Please sign in to comment.