是否可以将一个std::function从内部替换为另一个std::function?
以下代码未编译:
#include <iostream>
#include <functional>
int main()
{
std::function<void()> func = []()
{
std::cout << "a\n";
*this = std::move([]() { std::cout << "b\n"; });
};
func();
func();
func();
}它能被修改成编译吗?
现在的错误信息是:没有为这个lambda函数捕获' this‘--我完全理解这一点。然而,我不知道我怎么能捕捉到func的this-pointer。我想,它甚至还不是兰达内部的std::function?!这是怎么做到的?
背景:我想要实现的是:在第一次调用给定的std::function时,我想做一些初始化工作,然后用优化的函数替换原来的函数。我想为我的功能的用户透明地实现这一点。
上面示例的预期输出是:
一个 B B
发布于 2018-05-28 15:00:10
不能在lambda中使用this来引用lambda。this将只引用封闭类,在您的示例中,没有类,因此不能使用this。然而,您可以做的是捕获func并重新分配:
std::function<void()> func = [&func]()
{
std::cout << "a\n";
func = []() { std::cout << "b\n"; }; // note the missing move, a lambda
// is already an rvalue
};但是,请注意,如果让func超出其作用域(例如,通过按值从函数返回它)而不首先调用它(实际上重新分配了存储的函数对象),那么您将得到一个悬空引用。
我想,它甚至不是一个
std::function在兰博达,现在?!
实际上是的。名称在其声明器之后进入作用域,因此在=之前引入了类型为std::function<void()>的func。因此,在引入lambda的时候,您已经可以捕获func了。
发布于 2018-05-28 17:57:59
这在技术上解决了您的问题:
std::function<void()> func = [&func]{
std::cout << "a\n";
func = []{ std::cout << "b\n"; };
};但这不是一个好计划。std函数的生存期和行为与局部级堆栈变量相关联。拷贝几乎在任何意义上都不能完成你想做的事情--它们继续打印"a\b",除非它们分段错误,因为原始的func超出了范围。
为了解决这一问题,我们必须部署一些大型武器;首先,函数式编程女王Y Combinator女士:
std::function<void()> func = y_combinate( [](auto&& self){
std::cout << "a\n";
self = []{ std::cout << "b\"; };
} );Y组合器接受签名F = (F,Args...)->R的函数,然后返回签名(Args...)->R的函数。这是无状态语言如何管理递归时,您不能命名为您自己之前给您的名字。
在C++中编写Y组合器比您担心的要容易:
template<class F>
struct y_combinator_t {
F f;
template<class...Args>
auto operator()(Args&&...args)
-> typename std::result_of< F&( F&, Args&&... ) >::type
{
return f( f, std::forward<Args>(args)... );
}
};
template<class F>
y_combinator_t<typename std::decay<F>::type> y_combinate( F&& f ) {
return {std::forward<F>(f)};
}遗憾的是,这不起作用,因为传递给lambda的self类型实际上是原始lambda的类型。而b印刷灯是一种不相关的类型。因此,当您尝试self = []{ std::cout << "b\n"; }时,您会得到一个错误,嵌入到一些相对较深的模板垃圾邮件错误中。
悲伤,但只是暂时的挫折。
我们需要的是一种很难命名的类型--一个F = std::function<void(F)> --一个以同一类型的对象的实例作为其一个参数的std::function。
通常没有办法做到这一点,但有一点模版愚昧.在这里,我做到了之前。
然后,您的代码如下:
std::function<void()> func = y_combinate( recursive_func< void(own_type&) >([](auto&& self){
std::cout << "a\n";
self = [](auto&&){ std::cout << "b\n"; };
}) );对给定的func副本的调用首先打印"a\n",然后每个调用都打印"b\n"。B-打印机的副本也打印b,但是a-打印机的副本将在转换之前第一次打印。
实例化。
此代码中的self是一个recursive_func< void(own_type&) >,因此您可以在b-打印机中执行与在a-打印机中相同的操作。
https://stackoverflow.com/questions/50568739
复制相似问题