Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Get function arguments type as tuple

Problem

Given any function (or callable) type Function, how can I get its all arguments types as a tuple type ?

For example, I need a trait function_traits<Function>::arguments, where:

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>

My thought

First

I need to get the size of arguments, fortunately boost already has implemented function_traits<F>::arity

Then

Generate an std::integer_sequence from 1 to artify, map it to arguments type, but here comes the problem, to map integer_sequence, I need something like this:

function_traits<F>::arg_type<N> // -> N-th arg_type

but boost only provides this:

function_traits<F>::argN_type

Question

How can I implement function_traits<F>::arg_type<N> ? I can use c++ standard up to c++17

like image 626
Zang MingJie Avatar asked Aug 23 '19 08:08

Zang MingJie


People also ask

Can a function take a tuple as an argument?

A tuple can be an argument, but only one - it's just a variable of type tuple . In short, functions are built in such a way that they take an arbitrary number of arguments. The * and ** operators are able to unpack tuples/lists/dicts into arguments on one end, and pack them on the other end.

Is a function argument passed as list or tuple?

Due to the * prefix on the args variable, all extra arguments passed to the function are stored in args as a tuple.

Can you pass tuple as argument in Python?

In Python, you can unpack list , tuple , dict (dictionary) and pass its elements to function as arguments by adding * to list or tuple and ** to dictionary when calling function.

How can you get the type of arguments passed to a function?

There are two ways to pass arguments to a function: by reference or by value. Modifying an argument that's passed by reference is reflected globally, but modifying an argument that's passed by value is reflected only inside the function.


1 Answers

Something like this:

#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...>;
};

usage example:

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

online compiler

like image 98
user7860670 Avatar answered Sep 21 '22 12:09

user7860670