add function signature traits

This commit is contained in:
Timur A. Fatkhullin
2026-06-21 22:38:31 +03:00
parent 2d9579e962
commit aed4e2eba9
2 changed files with 85 additions and 0 deletions

View File

@@ -5,6 +5,7 @@ option(BUILD_EXAMPLES "Build examples" ON)
set(LIB_HEADERS set(LIB_HEADERS
include/snipplib/concepts/snplib_concepts.h include/snipplib/concepts/snplib_concepts.h
include/snipplib/concepts/snplib_traits.h
include/snipplib/utils/snplib_hash.h include/snipplib/utils/snplib_hash.h
include/snipplib/utils/snplib_string.h include/snipplib/utils/snplib_string.h
include/snipplib/utils/snplib_utils.h include/snipplib/utils/snplib_utils.h

View File

@@ -0,0 +1,84 @@
#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;
} // namespace snplib