Получить тип аргументов функции как кортеж
Проблема
Для любого типа функции (или вызываемого)
Function
, как мне получить все его типы аргументов как кортеж?
Например, мне нужна черта function_traits<Function>::arguments
, где:
int f();
typename function_traits<decltype(f)>::arguments // => gives me std::tuple<>
void g(int);
typename function_traits<decltype(g)>::arguments // => gives me std::tuple<int>
void h(int, int);
typename function_traits<decltype(h)>::arguments // => gives me std::tuple<int, int>
Моя мысль
Первый
Мне нужно получить размер аргументов, к счастью, boost уже реализовал function_traits<F>::arity
потом
Создать std::integer_sequence
от 1 до artify, сопоставьте его с типом аргументов, но здесь возникает проблема, чтобы сопоставить integer_sequence
, Мне нужно что-то вроде этого:
function_traits<F>::arg_type<N> // -> N-th arg_type
но boost обеспечивает только это:
function_traits<F>::argN_type
Вопрос
Как я могу реализовать function_traits<F>::arg_type<N>
? Могу использовать стандарт C++ до C++17
3 ответа
Что-то вроде этого:
#include <tuple>
template<typename x_Function> class
function_traits;
// specialization for functions
template<typename x_Result, typename... x_Args> class
function_traits<x_Result (x_Args...)>
{
public: using arguments = ::std::tuple<x_Args...>;
};
пример использования:
#include <type_traits>
int foo(int);
using foo_arguments = function_traits<decltype(foo)>::arguments;
static_assert(1 == ::std::tuple_size<foo_arguments>::value);
static_assert(::std::is_same_v<int, ::std::tuple_element<0, foo_arguments>::type>);
Слишком поздно играть?
Вы можете использовать C++17, так что... как насчет использования std::function
руководства по вычету?
template <typename T>
struct function_traits
{
template <typename R, typename ... As>
static std::tuple<As...> pro_args (std::function<R(As...)>);
using arguments = decltype(pro_args(std::function{std::declval<T>()}));
};
Ниже приведен полный пример компиляции.
#include <tuple>
#include <functional>
#include <type_traits>
int f ();
void g (int);
void h (int, int);
template <typename T>
struct function_traits
{
template <typename R, typename ... As>
static std::tuple<As...> pro_args (std::function<R(As...)>);
using arguments = decltype(pro_args(std::function{std::declval<T>()}));
};
int main ()
{
static_assert(std::is_same_v<std::tuple<>,
function_traits<decltype(f)>::arguments>);
static_assert(std::is_same_v<std::tuple<int>,
function_traits<decltype(g)>::arguments>);
static_assert(std::is_same_v<std::tuple<int, int>,
function_traits<decltype(h)>::arguments>);
}
Прошло несколько лет, но у меня есть очень эффективное (бесплатное) решение, если оно вам все еще нужно (если вы не привязаны к Boost). Неудовлетворенный найденными мной решениями для обработки особенностей функций, включая Boost (ни «function_traits», ни «callable_traits»), я написал свое собственное и сделал его доступным на GitHub для сообщества разработчиков C++. Я считаю, что это самая полная библиотека такого рода, которую вы сейчас найдете (профессионально написанная и полностью документированная).
См. /questions/41384894/poluchit-tipyi-parametrov-funktsii-c/66051989#66051989 (и указанную там ссылку).
Обратите внимание, что приведенный пример также касается вашего вопроса.