Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Metafunction to extract argument parameter lists from multiple functions pointers

For a single function it is possible to extract its parameter types like this:

template <class T>
struct Foo;

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

Would it be possible to do the same for a series of function pointers? That is, to be able to extract the arguments and then redeploy them in the same way? E.g. something like:

template <class.. T>
struct Foo;

template <class... Rets, class... Args>
struct Foo<Rets(*)(Args...)...>           // I wish this worked
{
    std::tuple<Rets(*)(Args...)...> fns;  // Ditto
}
like image 981
silverwidth Avatar asked May 22 '26 21:05

silverwidth


1 Answers

Late to the party, but this might be useful. First let's define some utilities:

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

Then a metafunction to check whether a type is a function pointer:

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> { };

Using these, let's write the class. The SFINAE toggle is placed first because the variadic pack takes up the right side:

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

Finally, a typedef to hide the SFINAE toggle from the user:

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

Voilà! Foo<void (*)(), int (*)(double)> goes to the specialization of Foo_impl which contains the adequate tuple, Foo<int, double> goes to the main template.

See it live on Coliru

like image 150
Quentin Avatar answered May 25 '26 12:05

Quentin



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!