Use C++20 concepts to require constraints on template parameters (#1977)

This commit is contained in:
Rangi
2026-05-22 17:54:34 -04:00
committed by GitHub
parent 728bed39d5
commit dce14fd4b8
12 changed files with 64 additions and 27 deletions
+20 -1
View File
@@ -3,6 +3,8 @@
#ifndef RGBDS_HELPERS_HPP
#define RGBDS_HELPERS_HPP
#include <type_traits>
// Ideally we'd use `std::unreachable`, but it has insufficient compiler support
#ifdef __GNUC__ // GCC or compatible
#ifdef NDEBUG
@@ -101,12 +103,29 @@ static inline int clz(unsigned int x) {
// MSVC does not inline `strlen()` or `.length()` of a constant string
template<int SizeOfString>
requires(SizeOfString > 0)
static constexpr int literal_strlen(char const (&)[SizeOfString]) {
return SizeOfString - 1; // Don't count the ending '\0'
}
// Concept for template parameters that must be an `enum` type
template<typename EnumT>
concept Enum = std::is_enum_v<EnumT>;
// Concept for template parameters that must be a function returning `void`
template<typename ProcedureFnT, typename... Args>
concept Procedure = std::is_void_v<std::invoke_result_t<ProcedureFnT, Args...>>;
// Concept for template parameters that must be a function returning a particular type
template<typename FnT, typename ReturnT, typename... Args>
concept InvocableR = std::is_invocable_r_v<ReturnT, FnT, Args...>;
// Concept for template parameters that must match a particular type modulo cv-qualifiers
template<typename T, typename UnqualifiedT>
concept QualifiedEquivalent = std::is_same_v<std::remove_cvref_t<T>, UnqualifiedT>;
// For ad-hoc RAII in place of a `defer` statement or cross-platform `__attribute__((cleanup))`
template<typename DeferredFnT>
template<Procedure DeferredFnT>
struct Defer {
DeferredFnT deferred;
Defer(DeferredFnT func) : deferred(func) {}