所以,我解释这个问题有点困难,希望你们能得到它。
让我们说我尝试(只是为了好玩)使用没有堆分配和奇怪的(读取慢)事情来创建我自己的Delegate类,而只是模板。
这或多或少是这个计划。
template <class T> class IDelegate;
template <class R, class ...T> class IDelegate<R(T...)>
{
public:
virtual R run(T...) = 0;
inline R operator() (T... args)
{
return run(args...);
}
// ...
};
template <class T> class Delegate;
template <class R, class ...T> class Delegate<R(T...)> : public IDelegate<R(T...)>
{
public:
Delegate(R(*function)(T...))
: IDelegate<R(T...)>(IDelegate<R(T...)>::FUNCTION),
function(function)
{}
Delegate(std::function<R(T...)>* stdf)
: IDelegate<R(T...)>(IDelegate<R(T...)>::FUNCTIONAL),
stdf(stdf)
{}
Delegate(std::function<R(T...)>& stdf)
: IDelegate<R(T...)>(IDelegate<R(T...)>::FUNCTIONAL),
stdf(stdf)
{}
virtual ~Delegate(){}
R run(T... args)
{
if(IDelegate<R(T...)>::delegate_type == IDelegate<R(T...)>::FUNCTION)
return function(args...);
else
return stdf->operator()(args...);
}
private:
union
{
R(*function)(T...);
const std::function<R(T...)>* stdf;
};
};
// ...
template <class R, class ...T> Delegate<R(T...)> * delegate(std::function<R(T...)>& f)
{
return new Delegate<R(T...)>(f);
}
该类已经与函数指针和方法很好地工作,我现在想要实现的是使它与lambdas一起使用并且通过使用std::function
类来实现它基本上有两个原因:< / p>
std::function
兼容,以供进一步使用。这是一个使用lambdas的工作示例:
auto f = new Delegate<void()>([]() { std::cout << "I'm a lambda!" << std::endl; });
f->run();
auto g = new Delegate<void(int)>([](int n) { std::cout << "Lambda: " << n << std::endl; });
g->run(5);
auto h = new Delegate<int(int)>(new std::function<int(int)>([&](int n) { return n*n; }));
std::cout << h->run(5) << std::endl;
当然,std::function
几乎总是被隐式调用,而std::function
对象是在幕后构建的。
但是,当我尝试使用delegate()
辅助函数执行此操作时,它无法正常工作。
auto e = delegate([]() { std::cout << "I'm a lambda!" << std::endl; });
clang++
出现以下错误。
$ clang++ delegate5.cpp --std=c++11 -O3
delegate5.cpp:263:11: error: no matching function for call to 'delegate'
auto e = delegate([]() { std::cout << "I'm a lambda!" << std::endl; });
^~~~~~~~
delegate5.cpp:120:52: note: candidate template ignored: could not match 'R (*)(T...)' against '(lambda at delegate5.cpp:263:20)'
template <class R, class ...T> Delegate<R(T...)> * delegate(R(*function)(T...))
^
delegate5.cpp:125:52: note: candidate template ignored: could not match 'function<type-parameter-0-0 (type-parameter-0-1...)>' against '(lambda at delegate5.cpp:263:20)'
template <class R, class ...T> Delegate<R(T...)> * delegate(std::function<R(T...)>& f)
^
delegate5.cpp:130:67: note: candidate function template not viable: requires 2 arguments, but 1 was provided
template <class O, class R, class ...T> Delegate<R(O::*)(T...)> * delegate(R(O::*method)(T...), O* parent)
^
delegate5.cpp:135:67: note: candidate function template not viable: requires 2 arguments, but 1 was provided
template <class O, class R, class ...T> Delegate<R(O::*)(T...)> * delegate(R(O::*method)(T...), O& parent)
^
delegate5.cpp:140:73: note: candidate function template not viable: requires 2 arguments, but 1 was provided
template <class O, class R, class ...T> Delegate<R(O::*)(T...) const> * delegate(R(O::*method)(T...) const, const O* parent)
^
delegate5.cpp:145:73: note: candidate function template not viable: requires 2 arguments, but 1 was provided
template <class O, class R, class ...T> Delegate<R(O::*)(T...) const> * delegate(R(O::*method)(T...) const, const O& parent)
^
1 error generated.
我想让它成功,可能是把它全部隐含起来,即使是在最后一个工作的lambda中,所以我可以实现类似的东西:
auto e = delegate([]() { std::cout << "I'm lambda!" << std::endl; });
auto g = delegate([](int n) { std::cout << "Lambda: " << n << std::endl; });
auto h = delegate([&](int n) { return n*n; });
很抱歉这篇长篇文章并提前致谢!