2014-12-18 13 views
5

Tôi muốn di chuyển an std::map đối tượng chứa khác. Ở dạng đơn giản:Cách chắp/sao chép đối tượng chứa STL vào đối tượng khác khi giá trị của nó không được sao chép có thể xây dựng được, ví dụ: std :: thread

#include<map> 
#include<thread> 
#include<vector> 
using namespace std; 

int main() 
{ 
    map<void*, vector<thread>> m1, m2; 
    // m1 is updated 

    m1.insert(m2.begin(), m2.end()); // <--- problem here 
    m2.clear(); // not required anymore 
} 

Tuy nhiên nó mang lại cho một trang của error:

error: use of deleted function ‘std::thread::thread(const std::thread&)’ 

Làm thế nào để thực hiện điều này?

+1

Vâng, bạn không thể sao chép các chủ đề. Đề nghị duy nhất tôi có là một 'bản đồ >>' (hoặc một 'bản đồ >>', tùy theo cái nào phù hợp hơn). – Wintermute

+0

Những gì bạn đang yêu cầu không thực sự có ý nghĩa - sao chép chuỗi có nghĩa là gì? Thay vào đó, bạn có muốn di chuyển không? – Cameron

+0

@Cameron, có thực sự nó di chuyển. Sau đó tôi sẽ chạy 'm2.clear()'. – iammilind

Trả lời

11

std::thread không sao chép constructible, bạn sẽ phải sử dụng một iterator cho phép di chuyển:

m1.insert(std::make_move_iterator(m2.begin()), 
      std::make_move_iterator(m2.end()); 

std::make_move_iterator trả về một iterator chuyên ngành lớp std::move_iterator có các thành viên truy cập (operator*()operator->()) trả về tham chiếu đến các giá trị không giống như các trình lặp lặp dựng sẵn trả về các giá trị. map::insert() ủy quyền hoạt động của nó thành map::emplace() nơi chuyển tiếp đối số vào loại phần tử.

Các trình tạo bản sao của chủ đề của bạn đã được gọi vì các đối tượng được trả về từ trình lặp lặp dựng sẵn được chuyển tiếp là lvalues ​​ và do đó được sao chép.

1

Giải pháp chung: di chuyển nó.

Tuy nhiên, trong khi std::move() có thể di chuyển một giá trị duy nhất, nó không thể di chuyển nhiều giá trị. Bạn sẽ cần phải viết một vòng lặp:

for (auto&& pair : m1) m2[pair.first] = std::move(pair.second) 
2

Tôi không nghĩ rằng bạn sẽ có thể chèn một loạt các yếu tố chỉ có thể di chuyển. Bạn sẽ có thể std::move() các yếu tố cá nhân, mặc dù:

for (auto& element: m2) { 
    m1.emplace(element.first, std::move(element.second)); 
} 
+0

Ngược lại, có 'std :: make_move_iterator'. Nhưng nó không giống như một bản sao ngữ nghĩa, tất nhiên. – Cameron

3

Di chuyển họ, sử dụng vòng lặp di chuyển:

m1.insert(make_move_iterator(begin(m2)), make_move_iterator(end(m2))); 
5

Chỉ cần cho đầy đủ, có một phiên bản ít được biết đến của std::move trong <algorithm> rằng sau một mô hình tương tự như std::copy.

Vì vậy, bạn có thể viết này:

move(begin(m2), end(m2), inserter(m1, begin(m1))); 
m2.clear(); 

reference here

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