在C ++中将函数参数检索为元组

时间:2011-11-22 09:37:27

标签: c++ function tuples

考虑我有这样的函数声明:

void foo(int x, float y);

class X {
  void anotherFoo(double a, int c);
};

如何获得与函数参数对应的元组?在上述情况下,它将是:

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

甚至更好,结果类型为第0个元素:

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

我知道boost::function_types::parameter_types可以做到这一点。但是,我对它是如何实现的原则感兴趣。

2 个答案:

答案 0 :(得分:9)

您可以获取与您的参数 types 对应的元组类型,如下所示:

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

这就是你想要的吗? 请注意,您可能需要添加一个或多个function_args重载,例如。为类方法提取类类型参数。

答案 1 :(得分:2)

最后找到了一种如何使用部分特化在C ++ 03中执行此操作的方法。不同数量的参数和const / volatile函数的大量重载是必要的,但想法如下:

/* 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)> { };

.
.
.

使用示例:

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

上述解决方案存在一些缺陷。它不处理函数引用,非成员函数或volatile / const volatile成员函数,但通过添加更多特化可以很容易地解释这些函数。

对于C ++ 11,@ Useless提到的方法更清晰,应该是首选。