获取函数参数类型作为元组

问题描述 投票:0回答:3

问题

给定任何函数(或可调用)类型

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

然后

从1生成一个

std::integer_sequence
到artify,将其映射到arguments类型,但是问题来了,要映射
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

c++ templates c++17 variadic-templates template-argument-deduction
3个回答
8
投票

类似这样的:

#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>);

在线编译器


4
投票

玩太晚了吗?

你可以使用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>);
 }

0
投票

现在已经是几年后的事了,但如果您仍然需要它(如果您没有锁定在 Boost 中),我有一个非常有效(免费)的解决方案。由于对我找到的处理函数特征的解决方案(包括 Boost 的解决方案)不满意(既不是“function_traits”也不是“callable_traits”),我编写了自己的解决方案,并将其发布在 GitHub 上供 C++ 开发人员社区使用。我相信它是您目前能找到的同类库中最完整的(专业编写和完整记录)。

参见 https://stackoverflow.com/a/76253527/698767(以及那里引用的链接)。

请注意,那里的示例也解决了您的问题。

© www.soinside.com 2019 - 2024. All rights reserved.