生成带有传递给模板的指针类型签名的函数

Generate function with signature of pointer's type passed to template

我想创建一个生成器,它为每个指向函数的指针创建一个 static 指针可以指向的函数:

template <auto &PtrToIsrHandler, auto MemberFunction> struct enable_member_isr_handler
{
    using TypeOfCFunPtr = std::remove_reference_t<decltype(PtrToIsrHandler)>;
    using TypeOfCFunPointed = std::remove_pointer_t<TypeOfCFunPtr>;
    using RetType = std::invoke_result_t<TypeOfCFunPointed>;
    static RetType isr_handler(/* dunno what to put here */)
    {
        return /* call MemberFunction here somehow */;
    }

    enable_member_isr_handler()
    {
        PtrToIsrHandler = isr_handler;
    }

};

isr_handler 方法的参数列表中,我尝试使用以下方法放置一个元组:

template <typename T> struct get_parameters;
template <typename Ret, typename... Args> struct get_parameters<Ret(Args...)>
{
    using args_t = std::tuple<Args...>;
};

但我明白了:

error: invalid conversion from void (*)(get_parameters<void()>)}’ to ‘void (*)()’

如何才能使 PtrToIsrHandler 成为指向 isr_handler 的有效指针?

如我的评论所述,获取参数列表的一种方法是使用偏特化并转发传入成员函数的类型。同样的方法也可以用在自由函数上。

#include <iostream>

template <auto MemberFunction, class MemberFunctionType>
struct handler_impl;

template <auto MemberFunction, class ReturnType, class ClassType, class... Args>
struct handler_impl<MemberFunction, ReturnType(ClassType::*)(Args...)> {
    // here you have access to return-type, class-type and args

    static ReturnType call_on_instance(ClassType& obj, Args... args) {
        return (obj.*MemberFunction)(args...);
    }
};

template <auto MemberFunction>
using handler = handler_impl<MemberFunction, decltype(MemberFunction)>;

struct Foo {
    int print(int x) {
        std::cout << x*x << std::endl;
        return x;
    }
};

int main() {
    Foo f;
    handler<&Foo::print>::call_on_instance(f, 7);
}

这里要记住的一件事是我们没有使用完美转发。最简单的方法就是简单地把 call_on_instance 做成一个模板函数,然后我们真的不需要关心参数和 return 值,我们可以让编译器推导它。

另一种选择是使用我上面展示的方法并使用 static_assert 来确保传入的参数列表有效,从而在以错误的方式使用时给出更好的错误消息。