/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ /* This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ /* Type traits for enums. */ #ifndef mozilla_EnumTypeTraits_h #define mozilla_EnumTypeTraits_h #include #include namespace mozilla { namespace detail { template struct EnumFitsWithinHelper; // Signed enum, signed storage. template struct EnumFitsWithinHelper : public std::integral_constant {}; // Signed enum, unsigned storage. template struct EnumFitsWithinHelper : public std::integral_constant {}; // Unsigned enum, signed storage. template struct EnumFitsWithinHelper : public std::integral_constant {}; // Unsigned enum, unsigned storage. template struct EnumFitsWithinHelper : public std::integral_constant {}; } // namespace detail /* * Type trait that determines whether the enum type T can fit within the * integral type Storage without data loss. This trait should be used with * caution with an enum type whose underlying type has not been explicitly * specified: for such enums, the C++ implementation is free to choose a type * no smaller than int whose range encompasses all possible values of the enum. * So for an enum with only small non-negative values, the underlying type may * be either int or unsigned int, depending on the whims of the implementation. */ template struct EnumTypeFitsWithin : public detail::EnumFitsWithinHelper< sizeof(T), std::is_signed::type>::value, sizeof(Storage), std::is_signed::value> { static_assert(std::is_enum::value, "must provide an enum type"); static_assert(std::is_integral::value, "must provide an integral type"); }; /* * Provides information about highest enum member value. * Each specialization of struct MaxEnumValue should define * "static constexpr unsigned int value". * * example: * * enum ExampleEnum * { * CAT = 0, * DOG, * HAMSTER * }; * * template <> * struct MaxEnumValue * { * static constexpr unsigned int value = static_cast(HAMSTER); * }; */ template struct MaxEnumValue; // no need to define the primary template /** * Get the underlying value of an enum, but typesafe. * * example: * * enum class Pet : int16_t { * Cat, * Dog, * Fish * }; * enum class Plant { * Flower, * Tree, * Vine * }; * UnderlyingValue(Pet::Fish) -> int16_t(2) * UnderlyingValue(Plant::Tree) -> int(1) */ template inline constexpr auto UnderlyingValue(const T v) { static_assert(std::is_enum_v); return static_cast::type>(v); } } // namespace mozilla #endif /* mozilla_EnumTypeTraits_h */