KPN/include/kpn/traits.hpp
2026-05-08 17:48:16 +02:00

87 lines
2.9 KiB
C++

#pragma once
#include <tuple>
#include <type_traits>
namespace kpn {
// ── Primary template — not defined; only specialisations match ────────────────
template<typename F>
struct function_traits;
// Free function
template<typename R, typename... Args>
struct function_traits<R(Args...)> {
using return_t = R;
using args = std::tuple<Args...>;
static constexpr std::size_t arity = sizeof...(Args);
};
// Function pointer
template<typename R, typename... Args>
struct function_traits<R(*)(Args...)> : function_traits<R(Args...)> {};
// Member function pointer (const)
template<typename C, typename R, typename... Args>
struct function_traits<R(C::*)(Args...) const> : function_traits<R(Args...)> {};
// Member function pointer (non-const)
template<typename C, typename R, typename... Args>
struct function_traits<R(C::*)(Args...)> : function_traits<R(Args...)> {};
// Callable (lambda / std::function) — delegate to operator()
template<typename F>
struct function_traits : function_traits<decltype(&F::operator())> {};
// ── Helpers ───────────────────────────────────────────────────────────────────
template<typename F>
using return_t = typename function_traits<std::remove_cvref_t<F>>::return_t;
template<typename F>
using args_t = typename function_traits<std::remove_cvref_t<F>>::args;
template<typename F>
inline constexpr std::size_t arity_v = function_traits<std::remove_cvref_t<F>>::arity;
// ── Tuple detection ───────────────────────────────────────────────────────────
template<typename T>
struct is_tuple : std::false_type {};
template<typename... Ts>
struct is_tuple<std::tuple<Ts...>> : std::true_type {};
template<typename T>
inline constexpr bool is_tuple_v = is_tuple<T>::value;
// ── Normalise return type to always be a tuple ────────────────────────────────
// void → std::tuple<>
// T (non-tup) → std::tuple<T>
// tuple<...> → tuple<...> (unchanged)
template<typename T>
struct normalise_return {
using type = std::tuple<T>;
};
template<>
struct normalise_return<void> {
using type = std::tuple<>;
};
template<typename... Ts>
struct normalise_return<std::tuple<Ts...>> {
using type = std::tuple<Ts...>;
};
template<typename T>
using normalised_return_t = typename normalise_return<T>::type;
// ── Output count from a function type ────────────────────────────────────────
template<typename F>
inline constexpr std::size_t output_count_v =
std::tuple_size_v<normalised_return_t<return_t<F>>>;
} // namespace kpn