我想创建一个生成器,它为每个指向函数的指针创建一个指针可以指向的 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/