我正在为可调用类型(函数,仿函数等指针)编写一个包装类。我想实现类似std :: function的东西。
我将指针定义为函数的构造函数:
template <typename Ret, typename... Args>
class function<Ret(Args...)>
{
public:
function(Ret (func)(Args...))
{
m_fn_ptr = func;
}
}
现在,让我们假设我想要像我这样使用我的课程:
int int_function(int n)
{
return n;
}
function<int(short)> wrapper(&int_function); // compile error
尽管short是隐式可转换为int编译器,但不能推导出模板参数并调用适当的构造函数。
然后我试了一下:
template <typename FRet, typename... FArgs>
function(FRet (func)(FArgs...))
{
m_fn_ptr = static_cast<Ret (*f)(Args...)>(func);
}
但是我得到了无效的静态演员。
我该如何解决?
答案 0 :(得分:1)
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。 super_func
是无国籍人。要在函数foo上使用它,请执行:
super_func< decltype(foo), &foo > super_foo;
并且你得到一个可调用的无状态空对象,其行为与foo
非常相似,除了你可以将它指定给指向任何兼容函数指针的指针,它会立即生成它&#34;&#34;在编译时。
可以将super_foo
输入您的功能对象。
在没有外部帮助的情况下,即时执行此操作并不起作用,因为我们需要foo
成为真正的静态信息。当它变成一个变量时,做无状态的为时已晚,所以我们不能使用lambda技巧(没有额外的pvoid)来生成我们想要的确切签名的函数指针。
你可以做一个宏:
#define SUPER(X) super_func< decltype(X), &X >{}
然后使用function
function<double()> f(SUPER(foo));
对象
另一种方法是存储额外指针的状态,并创建最快的代表&#34;风格类型擦除。 (该术语可以用Google搜索其中一个实现,每个实现都比上一个快。)
答案 1 :(得分:0)
我该如何解决?
创建wrapper
时使用正确的类型。
而不是使用
function<int(short)> wrapper(&int_function);
使用
function<int(int)> wrapper(&int_function);
请注意,使用int
和short
实例化的类模板是非常不同的类型,并且不能相互转换。
template <typename T> struct Foo {};
Foo<int> a;
Foo<short> b = a; // Not OK.
Foo<short> c;
Foo<int> d = c; // Not OK.
答案 2 :(得分:0)
您的function
构造函数需要一个指向函数的指针,该函数需要short
,而不是int
。修复是为它提供这样的功能。最简单的方法是使用带有空捕获列表的lambda,它可以隐式转换为函数指针:
function<int(short)> wrapper( [](short s) { return int_function(s); } );