#include <iostream>
#include <functional>
template <typename... Args>
std::function<void(Args...)> pushToEventLoop(std::function<void(Args...)> && p_function)
{
auto func = [p_function](Args... args) ->void
{
// This is what i would do here, but requires too much source code
//ThreadPool::enque(std::bind(p_function, args...));
// This is what i'll do for the sake of the example.
p_function(args...);
};
return func;
}
int main()
{
auto function(pushToEventLoop(std::function<void(char const *)>(std::bind(std::printf, std::placeholders::_1))));
auto function2 = std::bind(function, "Hello World!\n");
function2();
return 0;
}
是否有可能以及如何通过rvalue ref返回“func”变量?
我有一种感觉,这在某种程度上是完全疯了,但我想知道为什么,所以我可以恢复我的理智。
我不知道我是否做了一些可怕的错误。请提供反馈。
我构建了这个东西,以便我可以进行实际上刚刚发布到treadpool进行处理的回调,而不会让调用者或目标了解这一点。将他们联系在一起的中间人可以选择如何连接他们。
修改
好的,所以我认为当我返回func变量时会有复制。但显然它是由RVO处理的,因此不会发生复制。我还没有证实这一点,但现在我考虑一下,这是有道理的。
答案 0 :(得分:4)
如果您的问题是如何以最有效的方式返回lamba,那么只需按值返回它并使用自动返回简单扣除:
//this will actually return a lmabda and not a std::function
template <typename... Args>
auto pushToEventLoop(std::function<void(Args...)> && p_function)
{
return [f = std::move(p_function)](Args... args)
{
f(args...);
};
}
这将利用RVO并避免std::function
可能必须执行的任何动态内存分配。
如果你没有从中移动,那么拥有r值参考参数通常不会获得任何东西(除非你因为其他原因需要特定的接口)。为了在这里执行此操作,您可以利用c ++ 14的通用lambda捕获(编译器不能自己执行该优化,因为p_function
本身是l值)。
现在,如果你的问题是,如果/如何从函数返回(r-或l-值)对非静态局部变量的引用,那么答案就是:
永远不要这样做!
答案 1 :(得分:3)
我认为你要做的是将p_function
移到你的lambda中,同时避免复制?可能这是出于性能原因?
在这种情况下,你可能想要这样写:
template <typename... Args>
// return by value - because RVO will elide copies for us
std::function<void(Args...)>
// passing by r-value reference... ok no problem there
pushToEventLoop(std::function<void(Args...)> && p_function)
{
// but I want to MOVE my p_function into func
// this will require at least c++1y (c++14)
auto func = [p_function = std::move(p_function)](Args... args) ->void
{
// p_function has now been moved into the lambda ...
};
// ... p_function passed to us is now in a valid but undefined state
// so don't use it here
// allow RVO to do its thing
return func;
}