我想将一个对象放入std::map
,其构造函数不接受任何参数。但是,除了密钥之外,std::map::emplace
似乎还需要至少一个额外的参数。那么如何将零参数转发给构造函数呢?
答案 0 :(得分:43)
std::map<K, V>
的元素类型实际上是std::pair<K, V>
,因此当您放入地图时,参数将被转发到std::pair
的构造函数。这就是为什么你不能只传递密钥的原因:std::pair<K, V>
不能用一个参数构建(除非它是另一对相同的类型。)你可以传递零参数,但随后键将被初始化,这可能不是你想要的。
在大多数情况下,移动值会很便宜(并且键很小并且可以复制),你应该真的这样做:
M.emplace(k, V{});
其中V
是映射类型。它将被初始化并移动到容器中。 (此举甚至可能被忽略;我不确定。)
如果您无法移动,并且您确实需要就地构建V
,则必须使用分段构造构造函数...
M.emplace(std::piecewise_construct, std::make_tuple(k), std::make_tuple());
这会导致std::pair
使用k
构造第一个元素,使用零参数构造第二个元素(值初始化)。
答案 1 :(得分:16)
您可以明确创建pair
并将其传递给map::emplace
,或使用std::pair
的{{3}}。
struct foo {};
std::map<int, foo> m;
m.emplace(std::pair<int, foo>(1, {}));
m.emplace(std::piecewise_construct,
std::forward_as_tuple(2),
std::forward_as_tuple());
答案 2 :(得分:9)
当我必须创建std::map
个std::mutex
个对象时,我遇到了同样的问题。问题是std::mutex
既不可复制也不可移动,所以我需要“就地”构建它。
接受的答案对于这种情况不起作用(M.emplace(k, V{});
需要V可以移动)。而且我不想使用复杂且不太可读的std::piecewise_construct
选项(参见上面的其他答案)。
我的解决方案更简单 - 只需使用operator[]
- 它将使用其默认构造函数创建值并返回对它的引用。或者它只是找到并返回对现有项目的引用,而不创建新项目。
std::map<std::string, std::mutex> map;
std::mutex& GetMutexForFile(const std::string& filename)
{
return map[filename]; // constructs it inside the map if doesn't exist
}
答案 3 :(得分:3)
在C ++ 17中,您可以使用std::map::try_emplace
,它在内部使用std::piecewise_construct
,看起来并不那么麻烦。它还以键作为第一个参数(而不是像std::pair::pair()
一样将所有内容转发到emplace
中。)
#include <map>
struct A {
A() = default;
};
int main()
{
std::map<int, A> map;
map.emplace(std::piecewise_construct,
std::forward_as_tuple(10),
std::forward_as_tuple());
// ...vs...
map.try_emplace(10);
}
答案 4 :(得分:-2)
dirs[:] = [dir for dir in dirs if not (
re.search(r'\bEXP\b', dir) or
re.search(r'\b3.2\b', dir) or
re.search(r'\w+(?:-\w+)+', dir))]