如何在可变模板类中获取函数指针的参数类型?

46

这是对于这个问题的跟进:通用函数对象,适用于任意参数列表的函数

我有一个函数对象类(完整代码请参见上面的链接):

template<typename... ARGS>
class Foo
{
    std::function<void(ARGS...)> m_f;
public:
    Foo(std::function<void(ARGS...)> f) : m_f(f) {}
    void operator()(ARGS... args) const { m_f(args...); }
};

operator()中,我可以通过一个递归的“剥离”函数轻松访问args...,如Stroustrup的C++11 FAQ所述。
我的问题是:我想在构造函数中访问f的参数类型,即ARGS...。显然,我不能访问值,因为目前还没有值,但参数类型列表某种程度上被隐藏在f中,不是吗?
1个回答

87

您可以按照以下方式编写function_traits类,以发现参数类型、返回类型和参数数量:

template<typename T> 
struct function_traits;  

template<typename R, typename ...Args> 
struct function_traits<std::function<R(Args...)>>
{
    static const size_t nargs = sizeof...(Args);

    typedef R result_type;

    template <size_t i>
    struct arg
    {
        typedef typename std::tuple_element<i, std::tuple<Args...>>::type type;
    };
};

测试代码:

struct R{};
struct A{};
struct B{};

int main()
{
   typedef std::function<R(A,B)> fun;

   std::cout << std::is_same<R, function_traits<fun>::result_type>::value << std::endl;
   std::cout << std::is_same<A, function_traits<fun>::arg<0>::type>::value << std::endl;
   std::cout << std::is_same<B, function_traits<fun>::arg<1>::type>::value << std::endl;
} 

示例:http://ideone.com/YeN29


我明白你的意思。最后一个问题,这段代码是来自boost库吗?function_traits听起来很熟悉 ;) - steffen
1
@steffen:这个应该可以运行。你可能做错了什么。最好将代码发布在www.ideone.com上,这样我就能亲自看到错误了 - Nawaz
1
@steffen:问题在于当你使用ARG...时,你需要使用typenametemplate关键字来消除歧义。所以,你需要写成typename function_traits<fun_vararg>::template arg<0>::type,而不是function_traits<fun_vararg>::arg<0>::type。看看现在是否可以了:http://ideone.com/bysFS - Nawaz
1
@Nawaz 嗯,Wayback Machine在检索您已失效的“Demo”链接的内容方面没有提供帮助。:( - Drew Dormann
添加到通用标准库。 - Kalen
显示剩余5条评论

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接