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 * Get the underlying value of an enum, but typesafe.
69 * enum class Pet : int16_t {
79 * UnderlyingValue(Pet::Fish) -> int16_t(2)
80 * UnderlyingValue(Plant::Tree) -> int(1)
83 inline constexpr auto UnderlyingValue(const T v
) {
84 static_assert(std::is_enum_v
<T
>);
85 return static_cast<typename
std::underlying_type
<T
>::type
>(v
);
89 * Specialize either MaxContiguousEnumValue or MaxEnumValue to provide the
90 * highest enum member value for an enum class. Note that specializing
91 * MaxContiguousEnumValue will make MaxEnumValue just take its value from the
92 * MaxContiguousEnumValue specialization.
94 * Specialize MinContiguousEnumValue and MaxContiguousEnumValue to provide both
95 * lowest and highest enum member values for an enum class with contiguous
98 * Each specialization of these structs should define "static constexpr" member
99 * variable named "value".
111 * struct MaxEnumValue<ExampleEnum>
113 * static constexpr ExampleEnumvalue = HAMSTER;
117 template <typename T
>
118 struct MinContiguousEnumValue
{
119 static constexpr T value
= static_cast<T
>(0);
122 template <typename T
>
123 struct MaxContiguousEnumValue
;
125 template <typename T
>
126 struct MaxEnumValue
{
127 static constexpr auto value
= MaxContiguousEnumValue
<T
>::value
;
130 // Provides the min and max values for a contiguous enum (requires at least
131 // MaxContiguousEnumValue to be defined).
132 template <typename T
>
133 struct ContiguousEnumValues
{
134 static constexpr auto min
= MinContiguousEnumValue
<T
>::value
;
135 static constexpr auto max
= MaxContiguousEnumValue
<T
>::value
;
138 // Provides the total number of values for a contiguous enum (requires at least
139 // MaxContiguousEnumValue to be defined).
140 template <typename T
>
141 struct ContiguousEnumSize
{
142 static constexpr size_t value
=
143 UnderlyingValue(ContiguousEnumValues
<T
>::max
) + 1 -
144 UnderlyingValue(ContiguousEnumValues
<T
>::min
);
147 } // namespace mozilla
149 #endif /* mozilla_EnumTypeTraits_h */