问题
I'm trying to construct an object in a map that contains an atomic, so it can neither be copied nor moved AFAICT.
My reading of C++ reference is that map emplace
should be able to do this. But the following code does not compile because of deleted or non-existent constructors. Using make_pair
does not help.
#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
}
Is this possible, and if not, why not?
EDIT: Compiler is gcc 4.8.1, on Linux
回答1:
map.emplace(std::piecewise_construct, std::make_tuple(0), std::make_tuple())
will construct a zero-argument Z
at location 0
.
map[0]
will also do it if it is not already there.
emplace
takes the arguments to construct a std::pair<const K, V>
. std::pair
has a std::piecewise_construct_t
tagged constructor that takes two tuples, the first is used to construct the first argument, the second to construct the second argument.
so std::pair<const int, Z> test( std::piecewise_construct, std::make_tuple(0), std::make_tuple() )
constructs the test
s elements in-place, the const int
is constructed with (0)
. The Z
is constructed with ()
.
map.emplace
forwards is arguments to the std::pair
constructor.
回答2:
The simplest solution is to use operator[]
to construct the value inside the map. Then you can assign a value (or operate on it as needed).
回答3:
May be the following solution will be better, since atomic is not 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
}
来源:https://stackoverflow.com/questions/33423023/construct-in-place-an-unmoveable-object-in-a-map