2015-10-29 11 views
5

Ich versuche, ein Objekt in einer Karte zu erstellen, die eine atomare enthält, so dass es weder kopiert noch bewegt werden kann.Construct-in-Place ein unbewegliches Objekt in einer Karte

Meine Lesung von C++ reference ist, dass Karte emplace sollte dies tun können. Der folgende Code wird jedoch nicht kompiliert, weil Konstruktoren gelöscht oder nicht vorhanden sind. Die Verwendung von make_pair hilft nicht.

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

Ist das möglich, und wenn nicht, warum nicht?

EDIT: Compiler ist gcc 4.8.1, auf Linux

+1

Welche Compiler verwenden Sie? – Drop

+2

'emplace' nimmt die Konstruktorargumente, übergibt jedoch ein temporäres Objekt. –

+0

@NeilKirk Dann, wie sonst würde man den No-Arg-Konstruktor aufrufen? –

Antwort

13

map.emplace(std::piecewise_construct, std::make_tuple(0), std::make_tuple()) wird 0 ein Null-Argument Z an der Stelle errichten.

map[0] wird es auch tun, wenn es nicht schon da ist.

emplace nimmt die Argumente, um eine std::pair<const K, V> zu konstruieren. std::pair hat einen std::piecewise_construct_t getaggten Konstruktor, der zwei Tupel akzeptiert, der erste wird verwendet, um das erste Argument zu konstruieren, der zweite, um das zweite Argument zu konstruieren.

so baut die test s Elemente an Ort und Stelle, die const int ist mit (0) konstruiert. Die Z ist mit () konstruiert.

map.emplace Forwards ist Argumente für die std::pair Konstruktor.

2

Die einfachste Lösung besteht darin, operator[] zu verwenden, um den Wert in der Karte zu erstellen. Dann können Sie einen Wert zuweisen (oder bei Bedarf bearbeiten).

-1

Mai ist die folgende Lösung besser sein wird, da Atom nicht kopierbar ist:

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

Der Overhead von 'shared_ptr' ist nicht trivial. –