repr 0.1
Reconstructable string representations and more
All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Pages Concepts
arity.h
Go to the documentation of this file.
#pragma once
#include <cstddef>
#include <type_traits>
namespace librepr::detail {
struct Universal {
template <typename T>
/* implicit */ constexpr operator T(); // NOLINT
};
template <typename T>
requires std::is_aggregate_v<T>
struct ArityImpl {
template <typename... Fillers>
static consteval auto array_length(auto... parameters) {
if constexpr (requires { T{parameters..., {Fillers{}..., Universal{}}}; }) {
} else {
return sizeof...(Fillers);
}
}
static consteval auto arity_simple(auto... parameters) {
if constexpr (requires { T{parameters..., Universal{}}; }) {
} else {
return sizeof...(parameters);
}
}
template <typename... Trails>
static consteval auto arity_simple_ag(auto... parameters) {
if constexpr (requires { T{parameters..., {Universal{}, Universal{}}, Trails{}..., Universal{}}; }) {
} else {
return sizeof...(parameters) + sizeof...(Trails) + 1;
}
}
static consteval auto arity(std::size_t minus = 0, auto... parameters) {
if constexpr (requires { T{parameters..., {Universal{}, Universal{}}}; }) {
if constexpr (arity_simple_ag(parameters...) != arity_simple(parameters...)) {
minus += array_length(parameters...) - 1;
}
return arity(minus, parameters..., Universal{});
} else if constexpr (requires { T{parameters..., Universal{}}; }) {
return arity(minus, parameters..., Universal{});
} else {
return sizeof...(parameters) - minus;
}
}
};
template <typename T>
requires std::is_aggregate_v<T>
inline constexpr std::size_t arity = ArityImpl<T>::arity();
} // namespace librepr::detail