Files
snipplib/include/snipplib/concepts/snplib_traits.h
2026-08-06 13:27:13 +03:00

122 lines
3.2 KiB
C++

#pragma once
#include "snplib_concepts.h"
namespace snplib
{
/* deduce callable's signature */
// WARNING: it does not work for generic lambdas!
// helper classes
template <typename... Ts>
struct snplib_func_traits_helper_t;
template <typename R>
struct snplib_func_traits_helper_t<R> {
using ret_t = R;
using args_t = std::tuple<>;
using arg1_t = void;
static constexpr size_t arity = 0;
};
template <typename R, typename Arg, typename... Args>
struct snplib_func_traits_helper_t<R, Arg, Args...> {
using ret_t = R;
using args_t = std::tuple<Arg, Args...>;
using arg1_t = Arg;
static constexpr size_t arity = sizeof...(Args) + 1;
};
template <typename F>
struct snplib_func_traits_t {
// use of an empty struct here to match std::invoke_result behaivior (at least of GCC)
};
// special case
template <>
struct snplib_func_traits_t<std::nullptr_t> {
using ret_t = std::nullptr_t;
using args_t = std::tuple<>;
using arg1_t = std::nullptr_t;
static constexpr size_t arity = 0;
};
template <typename R, typename... Args>
struct snplib_func_traits_t<R (*)(Args...)> : snplib_func_traits_helper_t<R, Args...> {
};
template <typename R, typename... Args>
struct snplib_func_traits_t<R(Args...)> : snplib_func_traits_helper_t<R, Args...> {
};
template <typename C, typename R, typename... Args>
struct snplib_func_traits_t<R (C::*)(Args...)> : snplib_func_traits_helper_t<R, Args...> {
};
template <typename C, typename R, typename... Args>
struct snplib_func_traits_t<R (C::*)(Args...) const> : snplib_func_traits_helper_t<R, Args...> {
};
template <typename F>
requires snplib_callable_c<F>
struct snplib_func_traits_t<F> : snplib_func_traits_t<decltype(&F::operator())> {
};
template <typename F>
struct snplib_func_traits_t<F&> : snplib_func_traits_t<F> {
};
template <typename F>
struct snplib_func_traits_t<const F&> : snplib_func_traits_t<F> {
};
template <typename F>
struct snplib_func_traits_t<F&&> : snplib_func_traits_t<F> {
};
template <typename T>
using snplib_func_arg1_t = typename snplib_func_traits_t<T>::arg1_t;
/* create a std::tuple from the input types except the last one*/
template <typename... Ts>
struct snplib_tuple_except_last_helper_t;
template <typename T>
struct snplib_tuple_except_last_helper_t<T> {
using tuple_t = std::tuple<>;
};
template <typename T, typename... Ts>
struct snplib_tuple_except_last_helper_t<T, Ts...> {
using tuple_t =
decltype(std::tuple_cat(std::declval<std::tuple<T>>(),
std::declval<typename snplib_tuple_except_last_helper_t<Ts...>::tuple_t>()));
};
template <typename... Ts>
using snplib_tuple_except_last_t = typename snplib_tuple_except_last_helper_t<Ts...>::tuple_t;
template <typename... Ts>
struct snplib_last_in_pack_helper_t;
template <typename T>
struct snplib_last_in_pack_helper_t<T> {
using type = T;
};
template <typename T, typename... Ts>
struct snplib_last_in_pack_helper_t<T, Ts...> {
using type = typename snplib_last_in_pack_helper_t<Ts...>::type;
};
template <typename... Ts>
using snplib_last_in_pack_t = typename snplib_last_in_pack_helper_t<Ts...>::type;
} // namespace snplib