2015-10-29 43 views
5

我想在包含原子的地圖中構造一個對象,因此它既不能被複制也不能移動AFAICT。在地圖中構建一個不可移動的對象

我讀的C++ reference是地圖emplace應該能夠做到這一點。但是下面的代碼因爲刪除或不存在的構造函數而不能編譯。使用make_pair沒有幫助。

#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 
} 

這是可能的,如果沒有,爲什麼不呢?

編輯:編譯器是gcc 4.8.1,在Linux上

+1

你用什麼編譯器? – Drop

+2

'emplace'採用構造函數參數,但傳遞一個臨時對象。 –

+0

@NeilKirk那麼如何調用no-arg構造函數呢? –

回答

13

map.emplace(std::piecewise_construct, std::make_tuple(0), std::make_tuple())將在位置0構建一個零參數Z

map[0]也會這樣做,如果它不在那裏。

emplace需要參數來構造std::pair<const K, V>std::pair有一個std::piecewise_construct_t標記的構造函數,它接受兩個元組,第一個用於構造第一個參數,第二個構造第二個參數。

因此std::pair<const int, Z> test(std::piecewise_construct, std::make_tuple(0), std::make_tuple())構造test的元素在原地,const int構造與(0)Z()構建。

map.emplace轉發是構造函數std::pair的參數。

2

最簡單的解決方案是使用operator[]來構建地圖內的值。然後您可以分配一個值(或根據需要對其進行操作)。

-1

可能是下面的解決方案會更好,因爲原子是不可拷貝:

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

'shared_ptr'的開銷並不重要。 –