mirror of
https://github.com/revng/revng
synced 2026-06-21 14:07:57 +00:00
56 lines
1.9 KiB
C++
56 lines
1.9 KiB
C++
#pragma once
|
|
|
|
//
|
|
// This file is distributed under the MIT License. See LICENSE.md for details.
|
|
//
|
|
|
|
#include <cstddef>
|
|
#include <type_traits>
|
|
|
|
#include "revng/ADT/Concepts.h"
|
|
#include "revng/Support/Debug.h"
|
|
|
|
namespace revng::detail {
|
|
|
|
template<typename T>
|
|
concept EnumWithCount = requires {
|
|
requires std::is_enum<typename std::decay<T>::type>::value;
|
|
{ std::decay_t<T>::Count } -> std::convertible_to<size_t>;
|
|
};
|
|
|
|
} // namespace revng::detail
|
|
|
|
/// Calls the `operator()<Enumerator>()` of the callable `F` object passed
|
|
/// as the second parameter, where `Enumerator` corresponds to the runtime
|
|
/// argument passed as the first parameter (`Value`).
|
|
///
|
|
/// This can also be used as a simple way to instantiate a templated object
|
|
/// or function for every possible value of the specified enumeration.
|
|
///
|
|
/// \note: it requires the enumeration to contain the `Count` element to
|
|
/// mark the "one-after-the-last" enumerator.
|
|
///
|
|
/// \note: the behaviour is undefined if the enumeration is not continuous.
|
|
template<revng::detail::EnumWithCount Enum,
|
|
size_t From = 0,
|
|
size_t To = size_t(std::decay_t<Enum>::Count)>
|
|
constexpr inline auto enumSwitch(Enum Value, const auto &F) {
|
|
using Decayed = typename std::decay<Enum>::type;
|
|
|
|
constexpr Decayed Current = static_cast<Decayed>(From);
|
|
if (Current == Value)
|
|
return F.template operator()<Current>();
|
|
else if constexpr (From + 1 < To)
|
|
return enumSwitch<Enum, From + 1>(Value, F);
|
|
else
|
|
revng_abort("Unknown and/or unsupported enum value was encountered");
|
|
}
|
|
|
|
/// A specialized version of `enumSwitch` that allows skipping `SkippedCount`
|
|
/// first enumerators. The most typical use case it so avoid instantiating
|
|
/// templates for the first `Invalid = 0` enumerator.
|
|
template<size_t SkippedCount, revng::detail::EnumWithCount Enum>
|
|
constexpr inline auto skippingEnumSwitch(Enum Value, const auto &F) {
|
|
return enumSwitch<Enum, SkippedCount>(Value, F);
|
|
}
|