2016-12-16 15 views
5

Tôi muốn kết hợp hai vectơ trong một thread riêng biệtstd :: merge không làm việc với std :: async

int main() 
{ 
    vector<int> a(100); 
    vector<int> b(100); 
    vector<int> c(200); 
    std::async(std::launch::async, std::merge, a.begin(), a.end(), b.begin(), 
       b.end(), 
       c.begin()); 
} 

này không biên dịch

main.cpp: In function ‘int main()’: 
main.cpp:17:25: error: no matching function for call to ‘async(std::launch, <unresolved overloaded function type>, std::vector<int>::iterator, std::vector<int>::iterator, std::vector<int>::iterator, std::vector<int>::iterator, std::vector<int>::iterator)’ 
       c.begin()) 
         ^
In file included from main.cpp:4:0: 
/usr/include/c++/6.2.1/future:1709:5: note: candidate: template<class _Fn, class ... _Args> std::future<typename std::result_of<typename std::decay<_Tp>::type(typename std::decay<_BoundArgs>::type ...)>::type> std::async(std::launch, _Fn&&, _Args&& ...) 
    async(launch __policy, _Fn&& __fn, _Args&&... __args) 
    ^~~~~ 
/usr/include/c++/6.2.1/future:1709:5: note: template argument deduction/substitution failed: 
main.cpp:17:25: note: couldn't deduce template parameter ‘_Fn’ 
       c.begin()) 
         ^
In file included from main.cpp:4:0: 
/usr/include/c++/6.2.1/future:1739:5: note: candidate: template<class _Fn, class ... _Args> std::future<typename std::result_of<typename std::decay<_Tp>::type(typename std::decay<_BoundArgs>::type ...)>::type> std::async(_Fn&&, _Args&& ...) 
    async(_Fn&& __fn, _Args&&... __args) 
    ^~~~~ 
/usr/include/c++/6.2.1/future:1739:5: note: template argument deduction/substitution failed: 
/usr/include/c++/6.2.1/future: In substitution of ‘template<class _Fn, class ... _Args> std::future<typename std::result_of<typename std::decay<_Tp>::type(typename std::decay<_BoundArgs>::type ...)>::type> std::async(_Fn&&, _Args&& ...) [with _Fn = std::launch; _Args = {}]’: 
main.cpp:17:25: required from here 
/usr/include/c++/6.2.1/future:1739:5: error: no type named ‘type’ in ‘class std::result_of<std::launch()>’ 

Mặt khác, nếu tôi gọi

std::merge(a.begin(), a.end(), b.begin(), b.end(), c.begin()); 

Mọi thứ đều hoạt động tốt. Nếu tôi sử dụng một lambda - quá.

Tại sao?

Trả lời

10

std::merge là chức năng mẫu mẫu. Bắt một con trỏ đến một mẫu chức năng đòi hỏi bạn phải xác định rõ ràng những gì các thông số mẫu là:

std::async(std::launch::async, 
      &std::merge<decltype(a.begin()), decltype(b.begin()), decltype(c.begin())>, 
      a.begin(), a.end(), b.begin(), 
      b.end(), 
      c.begin()); 

Sử dụng một lambda đây có lẽ là giải pháp sạch và dễ đọc hơn:

auto merger = [&a, &b, &c] 
{ 
    return std::merge(a.begin(), a.end(), b.begin(), b.end(), c.begin()); 
}; 

std::async(std::launch::async, merger); 

Trong C++ 14, bạn có thể sử dụng lambda chung để chuyển trực tiếp đối số trong std::async. (Đó là vấn đề có hay không đó là một giải pháp tốt hơn so với chụp a, bc.) Ví dụ:

auto merger = [](auto&&... xs) 
{ 
    return std::merge(std::forward<decltype(xs)>(xs)...); 
}; 

std::async(std::launch::async, merger, 
      a.begin(), a.end(), b.begin(), b.end(), c.begin()); 
+0

@NathanOliver: Lỗi chính, cậu nói đúng - cố định câu trả lời. Cảm ơn. –

+0

@Kimi: trong ví dụ của OP chỉ các trình vòng lặp nhẹ được chuyển tới 'std :: merge', vì vậy tôi không bận tâm thêm việc chuyển tiếp hoàn hảo. Nhìn lại, một giải pháp tổng quát hơn là tốt hơn - tôi sẽ cập nhật câu trả lời của tôi. –

+0

Khi bạn đang chuyển nó sang 'std :: async' và đây là giá rẻ để sao chép các trình lặp, tôi muốn sử dụng tính năng capture-by-value không tham chiếu. – Yakk

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