2

考虑以下尝试vector在 a 中用数字键放置一个空map

#include <map>
#include <vector>

int main () {
    std::map<size_t, std::vector<size_t>> m;
    m.emplace(42, {});                          // FAILS
    m.insert({42, {}});                         // WORKS
}

调用emplace未能解决:

error: no matching function for call to ‘std::map<long unsigned int, std::vector<long unsigned int> >::emplace(int, <brace-enclosed initializer list>)’
     m.emplace(42, {});
                     ^
In file included from /usr/include/c++/8/map:61,
                 from map_emplace.cpp:1:
/usr/include/c++/8/bits/stl_map.h:574:2: note: candidate: ‘std::pair<typename std::_Rb_tree<_Key, std::pair<const _Key, _Tp>, std::_Select1st<std::pair<const _Key, _Tp> >, _Compare, typename __gnu_cxx::__alloc_traits<_Alloc>::rebind<std::pair<const _Key, _Tp> >::other>::iterator, bool> std::map<_Key, _Tp, _Compare, _Alloc>::emplace(_Args&& ...) [with _Args = {}; _Key = long unsigned int; _Tp = std::vector<long unsigned int>; _Compare = std::less<long unsigned int>; _Alloc = std::allocator<std::pair<const long unsigned int, std::vector<long unsigned int> > >; typename std::_Rb_tree<_Key, std::pair<const _Key, _Tp>, std::_Select1st<std::pair<const _Key, _Tp> >, _Compare, typename __gnu_cxx::__alloc_traits<_Alloc>::rebind<std::pair<const _Key, _Tp> >::other>::iterator = std::_Rb_tree_iterator<std::pair<const long unsigned int, std::vector<long unsigned int> > >]’
  emplace(_Args&&... __args)
  ^~~~~~~
/usr/include/c++/8/bits/stl_map.h:574:2: note:   candidate expects 0 arguments, 2 provided

尝试对向量的向量做同样的事情按预期工作(编辑:不使用时emplace_back,参见 Bo Persson 的回答):

    std::vector<std::vector<size_t>> v;
    v.emplace({});           // WORKS -- but does the wrong thing!
    v.emplace_back({});      // FAILS
    v.push_back({{}});       // WORKS

我对背后逻辑的粗略理解emplace是调用emplaceinsert应该给出相同的结果,不同之处在于 emplace 既不需要移动也不需要复制。对于这些类型,使用版本并没有太大的危害insert,因为向量的内容会被移动(在这种特定情况下,向量无论如何都是空的)。但总的来说,为什么这会失败std::map::emplace?使用 GCC 8.1。

4

3 回答 3

3

的签名map::emplace

template< class... Args >
std::pair<iterator,bool> emplace( Args&&... args );

并且{}没有类型,无法推断。

您可以使用,用于emplace

m.emplace(42, std::vector<std::size_t>{});

对于insert,(它的一个)签名是:

std::pair<iterator,bool> insert( const value_type& value );

so{42, {}}用于构造std::pair<const int, std::vector<size_t>>.

于 2018-05-16T11:11:15.677 回答
2

的签名emplace不同。

对于地图

template< class... Args >
std::pair<iterator,bool> emplace( Args&&... args );

与矢量

template< class... Args >
iterator emplace( const_iterator pos, Args&&... args );

如果map编译器无法Args从推断{},则它会失败。

因为vector它更容易,因为v.emplace({});已知的第一个参数是 a const_iterator。所以{}可以匹配一个默认构造的迭代器。

于 2018-05-16T11:13:13.610 回答
1

编译器无法推断出类型,{}因为emplace它是一个可变参数函数。强制类型,它将起作用:

m.emplace(42, (std::vector<size_t>){}); 
于 2018-05-16T11:10:35.530 回答