我想创建一个生成器,该函数针对每个指向函数的指针将创建一个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用作模板函数,那么我们实际上不需要关心参数和返回值,可以让编译器推断出它。

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

关于c++ - 通过传递给模板的指针类型签名生成函数,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/55033007/

10-11 22:59
查看更多