2015-10-29 15 views
5

Tôi đang cố gắng xây dựng một đối tượng trong bản đồ có chứa nguyên tử, do đó không thể sao chép hoặc di chuyển AFAICT.Xây dựng tại chỗ một đối tượng không thể di chuyển trong bản đồ

Việc đọc C++ reference của tôi là bản đồ emplace sẽ có thể thực hiện việc này. Nhưng đoạn mã sau không biên dịch vì các hàm tạo bị xóa hoặc không tồn tại. Sử dụng make_pair không giúp ích gì.

#include <atomic> 
#include <unordered_map> 

class Z { 
    std::atomic<int> i; 
}; 

std::unordered_map<int, Z> map; 

void test(void) { 
    map.emplace(0, Z()); // error 
    map[0] = Z(); // error 
} 

Điều này có thể, và nếu không, tại sao không?

EDIT: Compiler là gcc 4.8.1, trên Linux

+1

trình biên dịch nào bạn sử dụng? – Drop

+2

'emplace' nhận các đối số hàm tạo, nhưng bạn đang truyền một đối tượng tạm thời. –

+0

@NeilKirk Sau đó, làm thế nào khác sẽ gọi một constructor no-arg? –

Trả lời

13

map.emplace(std::piecewise_construct, std::make_tuple(0), std::make_tuple()) sẽ xây dựng một zero-luận Z tại địa điểm 0.

map[0] cũng sẽ làm điều đó nếu nó chưa có ở đó.

emplace lấy các đối số để tạo std::pair<const K, V>. std::pair có một constructor được gắn thẻ std::piecewise_construct_t có hai bộ dữ liệu, đầu tiên được sử dụng để tạo đối số đầu tiên, đối số thứ hai để tạo đối số thứ hai.

do đó std::pair<const int, Z> test(std::piecewise_construct, std::make_tuple(0), std::make_tuple()) xây dựng các phần tử test s tại chỗ, const int được xây dựng với (0). Các Z được xây dựng với ().

map.emplace chuyển tiếp là đối số cho hàm tạo std::pair.

2

Giải pháp đơn giản nhất là sử dụng operator[] để tạo giá trị bên trong bản đồ. Sau đó, bạn có thể gán một giá trị (hoặc hoạt động trên nó khi cần thiết).

-1

Có thể là giải pháp sau sẽ tốt hơn, kể từ khi nguyên tử là không copyable:

class Z { 
    std::atomic<int> i; 
}; 

std::unordered_map<int, std::shared_ptr<Z>> map; 

void test(void) { 
    map.emplace(0, std::make_shared<Z>()); // OK 
} 
+0

Chi phí của 'shared_ptr' là không nhỏ. –

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