考虑我有这样的函数声明:
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
可以做到这一点。但是,我对它是如何实现的原则感兴趣。
答案 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提到的方法更清晰,应该是首选。