像JavaScript这样的c ++期货/承诺?

jco*_*der 21 c++ promise

我一直在写一些javascript,我喜欢环境的一些事情就是它使用promises/future来为异步事件制作处理程序的方式.

在C++中,你必须在未来调用.get并阻塞,直到将来的结果可用,但在Javascript中你可以写.then(fn),它会在结果准备好时调用函数.重要的是,它在稍后与调用者在同一个线程中执行此操作,因此无需担心线程同步问题,至少与c ++中的问题不同.

我在用c ++思考像 -

auto fut = asyncImageLoader("cat.jpg");
fut.then([](Image img) { std::cout << "Image is now loaded\n" << image; });
Run Code Online (Sandbox Code Playgroud)

有没有办法在c ++中实现这一点?显然,它需要某种事件队列和事件循环来处理调度回调.我最终可能会编写代码来完成大部分工作,但是想看看是否有任何方法可以使用标准工具轻松实现目标.

Com*_*sMS 12

已经为即将到来的C++ 17标准提出了一个.then函数.std::future

Boost的未来实现(符合当前标准,但提供附加功能作为扩展)已经在较新版本(1.53或更新版本)中提供了该功能的一部分.

有关更完善的解决方案,请查看Boost.Asio库,它允许轻松实现异步控制流future.then.Asio的概念稍微复杂一些,因为它需要访问中心io_service对象来调度异步回调,并且需要手动管理工作线程.但原则上这是你所要求的非常好的匹配.


xha*_*k18 6

我不喜欢 C++ 的未来,所以我在这里写了一个 Promise 库作为 javascript https://github.com/xhawk18/promise-cpp

/* Convert callback to a promise (Defer) */
Defer myDelay(boost::asio::io_service &io, uint64_t time_ms) {
    return newPromise([&io, time_ms](Defer &d) {
        setTimeout(io, [d](bool cancelled) {
            if (cancelled)
                d.reject();
            else
                d.resolve();
        }, time_ms);
    });
}


void testTimer(io_service &io) {

    myDelay(io, 3000).then([&] {
        printf("timer after 3000 ms!\n");
        return myDelay(io, 1000);
    }).then([&] {
        printf("timer after 1000 ms!\n");
        return myDelay(io, 2000);
    }).then([] {
        printf("timer after 2000 ms!\n");
    }).fail([] {
        printf("timer cancelled!\n");
    });
}

int main() {
    io_service io;    
    testTimer(io);   
    io.run();
    return 0;
}
Run Code Online (Sandbox Code Playgroud)

与 Javascript Promise 相比,只是——

  1. 使用newPromise代替js的new Promise
  2. 使用lambda代替js函数
  3. 使用d.resolve代替js的resolve
  4. 使用d.reject代替js的reject

你可以解析/拒绝任何类型的参数,而不必关心c++模板中<>的麻烦。


Yak*_*ont 5

While then is proposed, you can implement your own infix then via the named operator technique.

Create a struct then_t {}; and a static then_t then;. Now override operator* on the left and right so that std::future<bool> *then* lambda creates a std::async that waits on the future, and passes the result to the lambda, then returns the return value of the lambda.

这需要大量的关心和关注,因为您必须仔细创建副本以避免悬空引用,并使用 r 和 l 值语法以使其完全高效。

您得到的最终语法是:

aut fut = asyncLoader("cat.jpg");
fut *then* [&](Image img) { std::cout << "Image loaded: " << img; };
Run Code Online (Sandbox Code Playgroud)

这非常接近你想要的。

如果你真的很聪明,你甚至可以让它也支持:

aut fut = asyncLoader("cat.jpg");
fut *then* [=] { std::cout << "Image loaded: " << fut.get(); };
Run Code Online (Sandbox Code Playgroud)

这消除了一些样板,有时会很有用。这需要asyncLoader返回 astd::shared_future而不是 a future