一个c++20的解决方案:
#define RETURNS(...) \
noexcept(noexcept(__VA_ARGS__)) \
-> decltype(__VA_ARGS__) \
{ return __VA_ARGS__; }
template<auto f, class R, class...Args>
struct explicit_function_caster {
using Sig=R(Args...);
using pSig=Sig*;
constexpr operator pSig()const {
return [](Args...args)->R {
return static_cast<R>(f(std::forward<Args>(args)...));
};
}
};
template<auto f>
struct overload_storer_t {
template<class R, class...Args>
constexpr (*operator R() const)(Args...) const {
return explicit_function_caster<f, R, Args...>{};
}
template<class...Args>
auto operator()(Args&&...args)
RETURNS( f( std::forward<Args>(args)... ) )
};
template<auto f>
overload_storer_t<f> generate_overloads={};
#define OVERLOADS_OF(...) \
generate_overloads< \
[](auto&&...args) \
RETURNS( __VA_ARGS__( decltype(args)(args)... ) ) \
>
这是很多样板文件,但可以得到:
ParentClass* (*arr[5])() = {
OVERLOADS_OF(fun1),
OVERLOADS_OF(fun2),
OVERLOADS_OF(fun3),
OVERLOADS_OF(fun4),
OVERLOADS_OF(fun5)
};
void (*arr2[5])() = {
OVERLOADS_OF(fun1),
OVERLOADS_OF(fun2),
OVERLOADS_OF(fun3),
OVERLOADS_OF(fun4),
OVERLOADS_OF(fun5)
};
基本上,
generate_overloads<x>
接受一个
constexpr
可调用对象
x
,并允许您在编译时将其转换为任何兼容签名的函数指针,并使用(几乎)任何签名进行调用。
与此同时,
OVERLOADS_OF
将函数名转换为一个
constexpr
对象,在该函数名上执行重载决议。我在这里使用它,因为作为函数指针的
fun3
不知道其默认参数,但在重载决议时它会知道。
在这种特定情况下,编写玩具 lambda 表达式来完成这项工作要容易得多;这只是尝试自动编写那些任意兼容签名的玩具 lambda 表达式。
ChildClass
没有继承ParentClass
吗? - CalethParentClass
。 我可以将其更改为ParentClass*而不是void *,但这样我就必须将数组中的每个条目强制转换。 相反,我当前选择在从数组中检索它之后进行转换。 - vc669fun4
两次,这是打字错误吗? - Fabio says Reinstate Monica