2015-01-28 16 views
6

Giả sử tôi có hai chức năng mà trở về tương lai:chức năng Kết hợp mà trở về tương lai

std::future<T> foo(int); 

std::future<U> bar(T const &); 

Tôi muốn kết hợp hai chức năng để một chức năng mà phải mất một int như tham số và trả về một std::future<U>. Tôi nên viết hàm này như thế nào? Có thể khái quát thành phần hàm cho các hàm trả về tương lai không?

std::future<U> foobar1(int x) 
{ 
    auto foo_x = foo(x); 
    return bar(foo_x.get()); 
} 

Chức năng này sẽ chặn cho đến khi tương lai trả lại foo xong, phải không? Điều này rõ ràng không phải là những gì tôi muốn.

std::future<U> foobar2(int x) 
{ 
    return std::async([=]() 
    { 
    auto foo_x = foo(x); 
    return bar(foo_x.get()).get(); 
    }); 
} 

Nó cảm thấy ngớ ngẩn để gọi get() về tương lai được trả về bởi bar chỉ để có nó biến thành một tương lai mới của std::async

std::future<U> foobar3(int x) 
{ 
    return foo(x).then([](std::future<T> f) 
    { 
    return bar(f.get()).get(); 
    }; 
} 

Ở đây, một lần nữa tôi phải gọi get() về tương lai được trả về bởi bar nếu không tôi sẽ có một số future<future<U>>. Đây có phải là cách tiếp cận chính xác không?

Trả lời

6

Điều bạn muốn là một đơn nguyên. std::future là gần như nhưng không hoàn toàn là một đơn nguyên nhưng thiếu khả năng soạn đúng chức năng bằng cách nhấc chúng như bạn đã nhận thấy. Để có một cuộc thảo luận chi tiết về điều này, vui lòng xem this blog post.

Tóm tắt là đối với C++ 17, phương pháp bổ sung đã được đề xuất cho std::future: next hoặc then sẽ có chức năng được áp dụng cho giá trị của tương lai khi có sẵn. Điều này tương đương với bind trong Haskell chẳng hạn (lưu ý: không phải std::bind).

Hãy lấy hai chức năng:

T foo(int); 
U bar(T const &); 

Ở đây chúng ta có một ánh xạ int -> T -> U, những gì bạn muốn là để nâng bản đồ này để int -> std::future<T> -> std::future<U>. Điều này có thể trông như thế sẽ là:

int x = 2; 
std::async([=](){return foo(x);}).then(bar); 

đâu then là một chức năng tự động bản đồ T -> U để std::future<T> -> std::future<U>.

Tuyên bố từ chối trách nhiệm: Tôi không phải là lập trình viên Haskell và nhận ra rằng tôi có thể đã có mọi thứ trộn lẫn. Tôi vui mừng chào đón sự điều chỉnh.

Các vấn đề liên quan