的super_func
是无状态的函数对象,可以转换到任何兼容的通话签名。
template<class T>using type=T;
template<class Sig, Sig* func>
struct super_func;
template<class R, class...Args, R(*func)(Args...)>
struct super_func<R(Args...), func> {
using Sig = R(Args...);
using pSig = Sig*;
template<class R2, class...Args2, class=std::enable_if_t<
std::is_convertible<
std::result_of_t<pSig(Args2...)>,
R2
>{}
&& !std::is_same<R2, void>{}
>>
constexpr operator type<R2(Args2...)>*() const {
return [](Args2...args)->R2{
return func(std::forward<Args2>(args)...);
};
}
template<class...Args2, class=std::enable_if_t<
std::is_same<
std::result_of_t<pSig(Args2...)>,
R
>{}
>>
constexpr operator type<void(Args2...)>*() const {
return [](Args2...args)->void{
func(std::forward<Args2>(args)...);
};
}
constexpr operator pSig() const {
return func;
}
constexpr R operator()(Args...args)const{
return func(std::forward<Args>(args)...);
}
};
live example。 A super_func
是无状态的。要使用它的函数foo,做到:
super_func< decltype(foo), &foo > super_foo;
,你会得到一个可调用无状态空的对象,它的行为很像0做,除非你可以把它分配给一个指针到任何兼容的函数指针,它产生它在编译时“即时”。
A super_foo
可以喂给你的功能对象。
没有外部帮助,在飞行中这样做不起作用,因为我们需要foo
成为一个真正的静态位信息。当它成为一个变量的时候,这种无状态的做法为时已晚,所以我们不能使用lambda技巧(没有额外的pvoid)为我们想要的确切签名生成一个函数指针。
你可以做一个宏:
#define SUPER(X) super_func< decltype(X), &X >{}
,然后用function<double()> f(SUPER(foo));
创建function
对象的另一种方法是存储一个额外的指针的价值状态,创造“以最快的速度代表“式擦除。 (该术语可以用于许多实现中的一个,每个实现都比上一个更快)。
如果你的函数类可以包含任意的可调用对象(如'std :: function'),这个特性是免费的。 – sbabbi
我想我可以实现这种类型的擦除成语,但有没有另一种解决方案? (因为类型擦除的经典实现将导致我动态分配内存) – eucpp
@EvgeniyMoiseenko嗯,你可以选择只接受函数指针并将它们保存在一个'void *'中。 – Columbo