Get function arguments as a tuple in C ++

I have function declarations like these:

void foo(int x, float y); class X { void anotherFoo(double a, int c); }; 

How can I get a tuple that matches function arguments? In the above case, it would be:

 boost::tuple<int, float> boost::tuple<X*, double, int> 

or even better with the result type as the 0th element:

 boost::tuple<void, int, float> boost::tuple<void, X*, double, int> 

I know that boost::function_types::parameter_types can do just that. However, I am interested in the principle of its implementation.

+6
source share
2 answers

You can get a tuple type matching your argument types, for example:

 template <typename R, typename... T> std::tuple<T...> function_args(R (*)(T...)) { return std::tuple<T...>(); } // get the tuple type typedef decltype(function_args(foo)) FooArgType; // create a default-initialised tuple auto args = function_args(foo); 

Is this what you want? Note that you may need to add one or more function_args overloads, for example. taking the class class parameter for class methods.

+9
source

Finally found a way to do this in C ++ 03 using partial specialization. Many overloads are needed for a different number of arguments and constant / unstable functions, but the idea is as follows:

 /* An empty template struct, this gets chosen if the given template parameter is not a member function */ template <typename _Func> struct MemberFunctionInfo { }; /* Specialization for parameterless functions */ template <typename _Result, typename _Class> struct MemberFunctionInfo<_Result (_Class::*) ()> { typedef _Class class_type; typedef _Result result_type; typedef boost::tuple<> parameter_types; enum { arity = 0 }; }; /* Specialization for parameterless const functions */ template <typename _Result, typename _Class> struct MemberFunctionInfo<_Result (_Class::*) () const> : MemberFunctionInfo<_Result (_Class::*) ()> { }; /* Specialization for functions with one parameter */ template <typename _Result, typename _Class, typename P0> struct MemberFunctionInfo<_Result (_Class::*) (P0)> { typedef _Class class_type; typedef _Result result_type; typedef boost::tuple<P0> parameter_types; enum { arity = 1 }; }; /* Specialization for const functions with one parameter */ template <typename _Result, typename _Class, typename P0> struct MemberFunctionInfo<_Result (_Class::*) (P0) const> : MemberFunctionInfo<_Result (_Class::*) (P0)> { }; . . . 

Usage example:

 template <typename MemFunc> int getArity(MemFunc fn) { // Can also use MemberFunctionInfo<MemFunc>::parameter_types with boost::mpl return MemberFunctionInfo<MemFunc>::arity; } 

The above solution has some disadvantages. It does not process references to functions, non-member functions, or volatile / const volatile member functions, but it is easy to take them into account by adding additional specializations.

For C ++ 11, the approach mentioned by @Useless is cleaner and should be preferred.

+2
source

Source: https://habr.com/ru/post/902087/


All Articles