我想创建一个生成器,该生成器将为每个指向函数的指针创建一个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
的有效指针?
答案 0 :(得分:1)
正如我的评论中提到的那样,获取参数列表的一种方法是使用部分特殊化并转发传入的成员函数的类型。自由函数也可以使用相同的方法。
#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
来确保传入的参数列表是有效的,从而以错误的方式使用时会给出更好的错误消息。