1 /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
2 /* This Source Code Form is subject to the terms of the Mozilla Public
3 * License, v. 2.0. If a copy of the MPL was not distributed with this
4 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
6 /* Type traits for enums. */
8 #ifndef mozilla_EnumTypeTraits_h
9 #define mozilla_EnumTypeTraits_h
12 #include <type_traits>
18 template <size_t EnumSize
, bool EnumSigned
, size_t StorageSize
,
20 struct EnumFitsWithinHelper
;
22 // Signed enum, signed storage.
23 template <size_t EnumSize
, size_t StorageSize
>
24 struct EnumFitsWithinHelper
<EnumSize
, true, StorageSize
, true>
25 : public std::integral_constant
<bool, (EnumSize
<= StorageSize
)> {};
27 // Signed enum, unsigned storage.
28 template <size_t EnumSize
, size_t StorageSize
>
29 struct EnumFitsWithinHelper
<EnumSize
, true, StorageSize
, false>
30 : public std::integral_constant
<bool, false> {};
32 // Unsigned enum, signed storage.
33 template <size_t EnumSize
, size_t StorageSize
>
34 struct EnumFitsWithinHelper
<EnumSize
, false, StorageSize
, true>
35 : public std::integral_constant
<bool, (EnumSize
* 2 <= StorageSize
)> {};
37 // Unsigned enum, unsigned storage.
38 template <size_t EnumSize
, size_t StorageSize
>
39 struct EnumFitsWithinHelper
<EnumSize
, false, StorageSize
, false>
40 : public std::integral_constant
<bool, (EnumSize
<= StorageSize
)> {};
45 * Type trait that determines whether the enum type T can fit within the
46 * integral type Storage without data loss. This trait should be used with
47 * caution with an enum type whose underlying type has not been explicitly
48 * specified: for such enums, the C++ implementation is free to choose a type
49 * no smaller than int whose range encompasses all possible values of the enum.
50 * So for an enum with only small non-negative values, the underlying type may
51 * be either int or unsigned int, depending on the whims of the implementation.
53 template <typename T
, typename Storage
>
54 struct EnumTypeFitsWithin
55 : public detail::EnumFitsWithinHelper
<
57 std::is_signed
<typename
std::underlying_type
<T
>::type
>::value
,
58 sizeof(Storage
), std::is_signed
<Storage
>::value
> {
59 static_assert(std::is_enum
<T
>::value
, "must provide an enum type");
60 static_assert(std::is_integral
<Storage
>::value
,
61 "must provide an integral type");
65 * Provides information about highest enum member value.
66 * Each specialization of struct MaxEnumValue should define
67 * "static constexpr unsigned int value".
79 * struct MaxEnumValue<ExampleEnum>
81 * static constexpr unsigned int value = static_cast<unsigned int>(HAMSTER);
85 struct MaxEnumValue
; // no need to define the primary template
88 * Get the underlying value of an enum, but typesafe.
92 * enum class Pet : int16_t {
102 * UnderlyingValue(Pet::Fish) -> int16_t(2)
103 * UnderlyingValue(Plant::Tree) -> int(1)
105 template <typename T
>
106 inline constexpr auto UnderlyingValue(const T v
) {
107 static_assert(std::is_enum_v
<T
>);
108 return static_cast<typename
std::underlying_type
<T
>::type
>(v
);
111 } // namespace mozilla
113 #endif /* mozilla_EnumTypeTraits_h */