将 boost::signals2::trackable 与 lambda 一起使用
Using boost::signals2::trackable with lambdas
我正在使用这样的模式,C++11:
class FooViewController {
void build() {
auto label = ...
network->doWork([] (const Result& r) {
label->setText(r.text);
});
}
}
FooViewController 可能会在 doWork
完成之前解构,从而导致崩溃。查看 boost::signals2,我正在考虑使用 boost::signals2::trackable
,它非常适合我的单线程用途,好处是我不必直接持有和管理我的连接,但我不是确定如何使用 lambda 获得这样的解决方案。
这是一个可用的 lambda 免费版本:
class Foo : public boost::signals2::trackable {
public:
void bar() {
printf("Fire!");
}
};
Usage:
boost::signals2::signal<void()> signal;
{
Foo test;
signal.connect(boost::bind(&Foo::bar, &test));
signal();
}
signal();
Output:
Fired!
// Note a second 'Fired!' did not occur, which is correct behavior
两个进球:
1-- 我想做类似的事情:
signal.connect(boost::bind([] {
printf("Fired!");
}, &test));
在 test
被拆除后不会调用 lambda。
2--不想直接管理.connect
返回的连接对象。
您可以使用 shared/weak 指针编写类似的代码:
#include <boost/signals2.hpp>
#include <boost/make_shared.hpp>
#include <boost/weak_ptr.hpp>
#include <iostream>
class Foo : public boost::signals2::trackable {
public:
void bar() {
printf("Fire!\n");
}
};
int main() {
boost::signals2::signal<void()> signal;
{
auto test = boost::make_shared<Foo>();
signal.connect([wp = boost::weak_ptr<Foo>(test)]
{
if (auto sp = wp.lock())
sp->bar();
else
std::cout << "expired\n";
}
);
signal();
}
signal();
}
版画
Fire!
expired
严格的c++11版本:Live On Coliru
找到参考 trackable_test.cpp 的答案:
struct short_lived : public boost::signals2::trackable {
~short_lived() {
cout << "I'm dying...!" << std::endl;
}
};
void main() {
typedef boost::signals2::signal<void()> sig_type;
sig_type s1;
short_lived* shorty = new short_lived();
s1.connect(boost::bind<void>([](const short_lived*) {
cout << "Fire!" << std::endl;
}, shorty));
s1();
delete shorty;
s1();
}
输出
Fire!
I'm dying...!
...和一个多参数示例(boost::bind 刷新器):
typedef boost::signals2::signal<void(int)> sig_type;
// ...same...
s1.connect(boost::bind<void>([](const short_lived*, int cannon) {
cout << "Fire " << cannon << "!" << std::endl;
}, shorty, _1));
s(1);
delete shorty;
s(2);
输出
Fire 1!
I'm dying...!
可以看出here:"Use of the trackable class is not recommended for new code"
也许选择 scoped_connection
或 track
。
示例:
#include <iostream>
#include <memory>
#include <boost/signals2.hpp>
struct short_lived : public boost::signals2::scoped_connection {
public:
short_lived(const boost::signals2::connection &conn) : boost::signals2::scoped_connection{conn}
{ }
~short_lived() {
std::cout << "I'm dying...1!" << std::endl;
}
};
int main() {
typedef boost::signals2::signal<void()> sig_type;
sig_type s1;
{
/* boost::signals2::scoped_connection */ short_lived conn{s1.connect([]() {
std::cout << "Fire1!" << std::endl;
})};
s1();
}
s1();
std::cout << std::endl;
{
auto lam = []() {
std::cout << "Fire2!" << std::endl;
};
/* shared_ptr with custom deleter that does not delete (since we didn't use new),
but prints a message */
std::shared_ptr<decltype(lam)> sptr{&lam, [](decltype(lam) *) { std::cout << "I'm dying...2!" << std::endl; }};
s1.connect(sig_type::slot_type(lam).track_foreign(sptr));
s1();
}
s1();
return 0;
}
我正在使用这样的模式,C++11:
class FooViewController {
void build() {
auto label = ...
network->doWork([] (const Result& r) {
label->setText(r.text);
});
}
}
FooViewController 可能会在 doWork
完成之前解构,从而导致崩溃。查看 boost::signals2,我正在考虑使用 boost::signals2::trackable
,它非常适合我的单线程用途,好处是我不必直接持有和管理我的连接,但我不是确定如何使用 lambda 获得这样的解决方案。
这是一个可用的 lambda 免费版本:
class Foo : public boost::signals2::trackable {
public:
void bar() {
printf("Fire!");
}
};
Usage:
boost::signals2::signal<void()> signal;
{
Foo test;
signal.connect(boost::bind(&Foo::bar, &test));
signal();
}
signal();
Output:
Fired!
// Note a second 'Fired!' did not occur, which is correct behavior
两个进球:
1-- 我想做类似的事情:
signal.connect(boost::bind([] {
printf("Fired!");
}, &test));
在 test
被拆除后不会调用 lambda。
2--不想直接管理.connect
返回的连接对象。
您可以使用 shared/weak 指针编写类似的代码:
#include <boost/signals2.hpp>
#include <boost/make_shared.hpp>
#include <boost/weak_ptr.hpp>
#include <iostream>
class Foo : public boost::signals2::trackable {
public:
void bar() {
printf("Fire!\n");
}
};
int main() {
boost::signals2::signal<void()> signal;
{
auto test = boost::make_shared<Foo>();
signal.connect([wp = boost::weak_ptr<Foo>(test)]
{
if (auto sp = wp.lock())
sp->bar();
else
std::cout << "expired\n";
}
);
signal();
}
signal();
}
版画
Fire!
expired
严格的c++11版本:Live On Coliru
找到参考 trackable_test.cpp 的答案:
struct short_lived : public boost::signals2::trackable {
~short_lived() {
cout << "I'm dying...!" << std::endl;
}
};
void main() {
typedef boost::signals2::signal<void()> sig_type;
sig_type s1;
short_lived* shorty = new short_lived();
s1.connect(boost::bind<void>([](const short_lived*) {
cout << "Fire!" << std::endl;
}, shorty));
s1();
delete shorty;
s1();
}
输出
Fire!
I'm dying...!
...和一个多参数示例(boost::bind 刷新器):
typedef boost::signals2::signal<void(int)> sig_type;
// ...same...
s1.connect(boost::bind<void>([](const short_lived*, int cannon) {
cout << "Fire " << cannon << "!" << std::endl;
}, shorty, _1));
s(1);
delete shorty;
s(2);
输出
Fire 1!
I'm dying...!
可以看出here:"Use of the trackable class is not recommended for new code"
也许选择 scoped_connection
或 track
。
示例:
#include <iostream>
#include <memory>
#include <boost/signals2.hpp>
struct short_lived : public boost::signals2::scoped_connection {
public:
short_lived(const boost::signals2::connection &conn) : boost::signals2::scoped_connection{conn}
{ }
~short_lived() {
std::cout << "I'm dying...1!" << std::endl;
}
};
int main() {
typedef boost::signals2::signal<void()> sig_type;
sig_type s1;
{
/* boost::signals2::scoped_connection */ short_lived conn{s1.connect([]() {
std::cout << "Fire1!" << std::endl;
})};
s1();
}
s1();
std::cout << std::endl;
{
auto lam = []() {
std::cout << "Fire2!" << std::endl;
};
/* shared_ptr with custom deleter that does not delete (since we didn't use new),
but prints a message */
std::shared_ptr<decltype(lam)> sptr{&lam, [](decltype(lam) *) { std::cout << "I'm dying...2!" << std::endl; }};
s1.connect(sig_type::slot_type(lam).track_foreign(sptr));
s1();
}
s1();
return 0;
}