Рассмотрим следующую попытку замещения пустого vector
с помощью цифровой клавиши в 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
Попытка сделать то же самое с вектором векторов работает как положено ( EDIT : не при использовании emplace_back
, см. Ответ Бо Перссона):
std::vector<std::vector<size_t>> v;
v.emplace({}); // WORKS -- but does the wrong thing!
v.emplace_back({}); // FAILS
v.push_back({{}}); // WORKS
Мое грубое понимание логики emplace
заключается в том, что вызовы emplace
и insert
должны давать один и тот же результат, с той разницей, что emplace не требует ни перемещения, ни копирования. Для этих типов нет особого вреда при использовании версии insert
, так как содержимое вектора будет перемещено (и в этом конкретном случае вектор пуст, во всяком случае). В общем, почему это не получается для std::map::emplace
? Использование GCC 8.1.