Chromium Code Reviews| Index: webrtc/base/safe_compare.h |
| diff --git a/webrtc/base/safe_compare.h b/webrtc/base/safe_compare.h |
| index 37ddf780c7241a5f55f3e42dc100a7a3a9bb62c2..39fb917a700862312c823bf12febb3dbc0fdf1b7 100644 |
| --- a/webrtc/base/safe_compare.h |
| +++ b/webrtc/base/safe_compare.h |
| @@ -145,26 +145,81 @@ RTC_SAFECMP_MAKE_OP(GtOp, >) |
| RTC_SAFECMP_MAKE_OP(GeOp, >=) |
| #undef RTC_SAFECMP_MAKE_OP |
| +// Determines if the given type is an enum that converts implicitly to |
| +// an integral type. |
| +template <typename T> |
| +struct IsIntEnum { |
| + private: |
| + // This overload is used if the type is an enum, and unary plus |
| + // compiles and turns it into an integral type. |
| + template <typename X, |
| + typename std::enable_if< |
| + std::is_enum<X>::value && |
| + std::is_integral<decltype(+std::declval<X>())>::value>::type* = |
| + nullptr> |
| + static int Test(int); |
| + |
| + // Otherwise, this overload is used. |
| + template <typename> |
| + static char Test(...); |
|
ossu
2016/11/28 14:14:34
I tried to find an answer to this, and clearly thi
kwiberg-webrtc
2016/11/28 23:20:37
Yes, they can be the same size, but I think they'd
ossu
2016/11/29 10:28:23
Cool beans! Then I'm satisfied. :)
|
| + |
| + public: |
| + static constexpr bool value = |
| + std::is_same<decltype(Test<typename std::remove_reference<T>::type>(0)), |
| + int>::value; |
| +}; |
| + |
| +// Determines if the given type is integral, or an enum that |
| +// converts implicitly to an integral type. |
| +template <typename T> |
| +struct IsIntlike { |
| + private: |
| + using X = typename std::remove_reference<T>::type; |
| + |
| + public: |
| + static constexpr bool value = |
| + std::is_integral<X>::value || IsIntEnum<X>::value; |
| +}; |
| + |
| +namespace test_enum_intlike { |
| + |
| +enum E1 { e1 }; |
| +enum { e2 }; |
| +enum class E3 { e3 }; |
| +struct S {}; |
| + |
| +static_assert(IsIntEnum<E1>::value, ""); |
| +static_assert(IsIntEnum<decltype(e2)>::value, ""); |
| +static_assert(!IsIntEnum<E3>::value, ""); |
| +static_assert(!IsIntEnum<int>::value, ""); |
| +static_assert(!IsIntEnum<float>::value, ""); |
| +static_assert(!IsIntEnum<S>::value, ""); |
| + |
| +static_assert(IsIntlike<E1>::value, ""); |
| +static_assert(IsIntlike<decltype(e2)>::value, ""); |
| +static_assert(!IsIntlike<E3>::value, ""); |
| +static_assert(IsIntlike<int>::value, ""); |
| +static_assert(!IsIntlike<float>::value, ""); |
| +static_assert(!IsIntlike<S>::value, ""); |
| + |
| +} // test_enum_intlike |
| } // namespace safe_cmp_impl |
| -#define RTC_SAFECMP_MAKE_FUN(name) \ |
| - template < \ |
| - typename T1, typename T2, \ |
| - typename std::enable_if< \ |
| - std::is_integral<typename std::remove_reference<T1>::type>::value && \ |
| - std::is_integral<typename std::remove_reference<T2>::type>::value>:: \ |
| - type* = nullptr> \ |
| - inline bool name(T1 a, T2 b) { \ |
| - return safe_cmp_impl::Cmp<safe_cmp_impl::name##Op>(a, b); \ |
| - } \ |
| - template <typename T1, typename T2, \ |
| - typename std::enable_if< \ |
| - !std::is_integral< \ |
| - typename std::remove_reference<T1>::type>::value || \ |
| - !std::is_integral<typename std::remove_reference<T2>::type>:: \ |
| - value>::type* = nullptr> \ |
| - inline bool name(T1&& a, T2&& b) { \ |
| - return safe_cmp_impl::name##Op::Op(a, b); \ |
| +#define RTC_SAFECMP_MAKE_FUN(name) \ |
| + template <typename T1, typename T2, \ |
| + typename std::enable_if< \ |
| + safe_cmp_impl::IsIntlike<T1>::value && \ |
| + safe_cmp_impl::IsIntlike<T2>::value>::type* = nullptr> \ |
| + inline bool name(T1 a, T2 b) { \ |
| + /* Unary plus here turns enums into real integral types. */ \ |
| + return safe_cmp_impl::Cmp<safe_cmp_impl::name##Op>(+a, +b); \ |
| + } \ |
| + template <typename T1, typename T2, \ |
| + typename std::enable_if< \ |
| + !safe_cmp_impl::IsIntlike<T1>::value || \ |
| + !safe_cmp_impl::IsIntlike<T2>::value>::type* = nullptr> \ |
| + inline bool name(T1&& a, T2&& b) { \ |
| + return safe_cmp_impl::name##Op::Op(a, b); \ |
| } |
| RTC_SAFECMP_MAKE_FUN(Eq) |
| RTC_SAFECMP_MAKE_FUN(Ne) |