Получить тип аргументов функции как кортеж

Проблема

Для любого типа функции (или вызываемого) 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 (и указанную там ссылку).

Обратите внимание, что приведенный пример также касается вашего вопроса.

Другие вопросы по тегам