从多个函数指针中提取参数参数列表的元函数

Metafunction to extract argument parameter lists from multiple functions pointers

对于单个函数,可以像这样提取其参数类型:

template <class T>
struct Foo;

template <class Ret, class... Args>
struct Foo<Ret(*)(Args...)> { /* stuff */ };

是否可以对一系列函数指针做同样的事情?那是, 能够提取参数然后以相同的方式重新部署它们?例如。类似于:

template <class.. T>
struct Foo;

template <class... Rets, class... Args>
struct Foo<Rets(*)(Args...)...>           // I wish this worked
{
    std::tuple<Rets(*)(Args...)...> fns;  // Ditto
}

聚会迟到了,但这可能会有用。首先让我们定义一些实用程序:

template <class... T>
using void_t = void;

template <bool...> struct bool_pack;

template <bool... v>
using all_true = std::is_same<bool_pack<true, v...>, bool_pack<v..., true>>;

然后一个元函数来检查一个类型是否是一个函数指针:

template <class F>
struct is_function_pointer : std::integral_constant<bool, false> { };

template <class Ret, class... Args>
struct is_function_pointer<Ret (*)(Args...)> : std::integral_constant<bool, true> { };

使用这些,让我们编写 class。 SFINAE 开关放在第一位,因为可变参数包占据了右侧:

template <class = void_t<>, class... T>
struct Foo_impl;

template <class... FuncPtrs>
struct Foo_impl<
    std::enable_if_t<all_true<is_function_pointer<FuncPtrs>{}...>{}>,
    FuncPtrs...
> {
    std::tuple<FuncPtrs...> fns;
};

最后,对用户隐藏 SFINAE 开关的 typedef:

template <class... T>
using Foo = Foo_impl<void_t<>, T...>;

瞧! Foo<void (*)(), int (*)(double)> 转到包含足够元组的 Foo_impl 的特化,Foo<int, double> 转到主模板。

See it live on Coliru