Backed out 4 changesets (bug 1834274) Mn failures on browser/components/tests/marione...
[gecko.git] / mfbt / EnumTypeTraits.h
blob528e1db8a79431def196abe9d9465cdf3d6f4b64
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
11 #include <stddef.h>
12 #include <type_traits>
14 namespace mozilla {
16 namespace detail {
18 template <size_t EnumSize, bool EnumSigned, size_t StorageSize,
19 bool StorageSigned>
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)> {};
42 } // namespace detail
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<
56 sizeof(T),
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".
69 * example:
71 * enum ExampleEnum
72 * {
73 * CAT = 0,
74 * DOG,
75 * HAMSTER
76 * };
78 * template <>
79 * struct MaxEnumValue<ExampleEnum>
80 * {
81 * static constexpr unsigned int value = static_cast<unsigned int>(HAMSTER);
82 * };
84 template <typename T>
85 struct MaxEnumValue; // no need to define the primary template
87 /**
88 * Get the underlying value of an enum, but typesafe.
90 * example:
92 * enum class Pet : int16_t {
93 * Cat,
94 * Dog,
95 * Fish
96 * };
97 * enum class Plant {
98 * Flower,
99 * Tree,
100 * Vine
101 * };
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 */