Невозможно вставить в стандартную карту

У меня есть стандартная карта, состоящая из int и указателя на структуру. Однако, используя функцию вставки, я не могу добавить то же самое. Сообщение об ошибке кажется слишком сложным для меня, чтобы добраться до сути.

#include <iostream>
#include <map>
using namespace std;

typedef struct 
{

}NODE;

int main()
{
    std::map<int, NODE*> mp;
    int i = 0;
    mp.insert(i, new NODE());

    return 0;
}

Язык ошибок немного загадочен. Я пытаюсь добавить указатель int и NODE к карте указателя int и NODE. Почему это дает мне несоответствующую функцию?

main.cpp: In function ‘int main()’:
main.cpp:22:28: error: no matching function for call to ‘std::map::insert(int&, NODE*)’
     mp.insert(i, new NODE());
                            ^
In file included from /usr/include/c++/7/map:61:0,
                 from main.cpp:10:
/usr/include/c++/7/bits/stl_map.h:621:7: note: candidate: std::map<_Key, _Tp, _Compare, _Alloc>::insert_return_type std::map<_Key, _Tp, _Compare, _Alloc>::insert(std::map<_Key, _Tp, _Compare, _Alloc>::node_type&&) [with _Key = int; _Tp = NODE*; _Compare = std::less; _Alloc = std::allocator >; std::map<_Key, _Tp, _Compare, _Alloc>::insert_return_type = std::_Node_insert_return >, std::_Node_handle, std::allocator > > > >; std::map<_Key, _Tp, _Compare, _Alloc>::node_type = std::_Node_handle, std::allocator > > >]
       insert(node_type&& __nh)
       ^~~~~~
/usr/include/c++/7/bits/stl_map.h:621:7: note:   candidate expects 1 argument, 2 provided
/usr/include/c++/7/bits/stl_map.h:626:7: note: candidate: std::map<_Key, _Tp, _Compare, _Alloc>::iterator std::map<_Key, _Tp, _Compare, _Alloc>::insert(std::map<_Key, _Tp, _Compare, _Alloc>::const_iterator, std::map<_Key, _Tp, _Compare, _Alloc>::node_type&&) [with _Key = int; _Tp = NODE*; _Compare = std::less; _Alloc = std::allocator >; std::map<_Key, _Tp, _Compare, _Alloc>::iterator = std::_Rb_tree_iterator >; std::map<_Key, _Tp, _Compare, _Alloc>::const_iterator = std::_Rb_tree_const_iterator >; std::map<_Key, _Tp, _Compare, _Alloc>::node_type = std::_Node_handle, std::allocator > > >]
       insert(const_iterator __hint, node_type&& __nh)
       ^~~~~~
/usr/include/c++/7/bits/stl_map.h:626:7: note:   no known conversion for argument 1 from ‘int’ to ‘std::map::const_iterator {aka std::_Rb_tree_const_iterator >}’
/usr/include/c++/7/bits/stl_map.h:795:7: note: candidate: std::pair, std::_Select1st >, _Compare, typename __gnu_cxx::__alloc_traits<_Alloc>::rebind >::other>::iterator, bool> std::map<_Key, _Tp, _Compare, _Alloc>::insert(const value_type&) [with _Key = int; _Tp = NODE*; _Compare = std::less; _Alloc = std::allocator >; typename std::_Rb_tree<_Key, std::pair, std::_Select1st >, _Compare, typename __gnu_cxx::__alloc_traits<_Alloc>::rebind >::other>::iterator = std::_Rb_tree_iterator >; std::map<_Key, _Tp, _Compare, _Alloc>::value_type = std::pair]
       insert(const value_type& __x)
       ^~~~~~
/usr/include/c++/7/bits/stl_map.h:795:7: note:   candidate expects 1 argument, 2 provided
/usr/include/c++/7/bits/stl_map.h:802:7: note: candidate: std::pair, std::_Select1st >, _Compare, typename __gnu_cxx::__alloc_traits<_Alloc>::rebind >::other>::iterator, bool> std::map<_Key, _Tp, _Compare, _Alloc>::insert(std::map<_Key, _Tp, _Compare, _Alloc>::value_type&&) [with _Key = int; _Tp = NODE*; _Compare = std::less; _Alloc = std::allocator >; typename std::_Rb_tree<_Key, std::pair, std::_Select1st >, _Compare, typename __gnu_cxx::__alloc_traits<_Alloc>::rebind >::other>::iterator = std::_Rb_tree_iterator >; std::map<_Key, _Tp, _Compare, _Alloc>::value_type = std::pair]
       insert(value_type&& __x)
       ^~~~~~
/usr/include/c++/7/bits/stl_map.h:802:7: note:   candidate expects 1 argument, 2 provided
/usr/include/c++/7/bits/stl_map.h:808:2: note: candidate: template std::__enable_if_t, _Pair>::value, std::pair, std::_Select1st >, _Compare, typename __gnu_cxx::__alloc_traits<_Alloc>::rebind >::other>::iterator, bool> > std::map<_Key, _Tp, _Compare, _Alloc>::insert(_Pair&&) [with _Pair = _Pair; _Key = int; _Tp = NODE*; _Compare = std::less; _Alloc = std::allocator >]
  insert(_Pair&& __x)
  ^~~~~~
/usr/include/c++/7/bits/stl_map.h:808:2: note:   template argument deduction/substitution failed:
main.cpp:22:28: note:   candidate expects 1 argument, 2 provided
     mp.insert(i, new NODE());
                            ^
In file included from /usr/include/c++/7/map:61:0,
                 from main.cpp:10:
/usr/include/c++/7/bits/stl_map.h:822:7: note: candidate: void std::map<_Key, _Tp, _Compare, _Alloc>::insert(std::initializer_list >) [with _Key = int; _Tp = NODE*; _Compare = std::less; _Alloc = std::allocator >]
       insert(std::initializer_list<value_type> __list)
       ^~~~~~
/usr/include/c++/7/bits/stl_map.h:822:7: note:   candidate expects 1 argument, 2 provided
/usr/include/c++/7/bits/stl_map.h:852:7: note: candidate: std::map<_Key, _Tp, _Compare, _Alloc>::iterator std::map<_Key, _Tp, _Compare, _Alloc>::insert(std::map<_Key, _Tp, _Compare, _Alloc>::const_iterator, const value_type&) [with _Key = int; _Tp = NODE*; _Compare = std::less; _Alloc = std::allocator >; std::map<_Key, _Tp, _Compare, _Alloc>::iterator = std::_Rb_tree_iterator >; std::map<_Key, _Tp, _Compare, _Alloc>::const_iterator = std::_Rb_tree_const_iterator >; std::map<_Key, _Tp, _Compare, _Alloc>::value_type = std::pair]
       insert(const_iterator __position, const value_type& __x)
       ^~~~~~
/usr/include/c++/7/bits/stl_map.h:852:7: note:   no known conversion for argument 1 from ‘int’ to ‘std::map::const_iterator {aka std::_Rb_tree_const_iterator >}’
/usr/include/c++/7/bits/stl_map.h:862:7: note: candidate: std::map<_Key, _Tp, _Compare, _Alloc>::iterator std::map<_Key, _Tp, _Compare, _Alloc>::insert(std::map<_Key, _Tp, _Compare, _Alloc>::const_iterator, std::map<_Key, _Tp, _Compare, _Alloc>::value_type&&) [with _Key = int; _Tp = NODE*; _Compare = std::less; _Alloc = std::allocator >; std::map<_Key, _Tp, _Compare, _Alloc>::iterator = std::_Rb_tree_iterator >; std::map<_Key, _Tp, _Compare, _Alloc>::const_iterator = std::_Rb_tree_const_iterator >; std::map<_Key, _Tp, _Compare, _Alloc>::value_type = std::pair]
       insert(const_iterator __position, value_type&& __x)
       ^~~~~~
/usr/include/c++/7/bits/stl_map.h:862:7: note:   no known conversion for argument 1 from ‘int’ to ‘std::map::const_iterator {aka std::_Rb_tree_const_iterator >}’
/usr/include/c++/7/bits/stl_map.h:867:2: note: candidate: template std::__enable_if_t, _Pair>::value, typename std::_Rb_tree<_Key, std::pair, std::_Select1st >, _Compare, typename __gnu_cxx::__alloc_traits<_Alloc>::rebind >::other>::iterator> std::map<_Key, _Tp, _Compare, _Alloc>::insert(std::map<_Key, _Tp, _Compare, _Alloc>::const_iterator, _Pair&&) [with _Pair = _Pair; _Key = int; _Tp = NODE*; _Compare = std::less; _Alloc = std::allocator >]
  insert(const_iterator __position, _Pair&& __x)
  ^~~~~~
/usr/include/c++/7/bits/stl_map.h:867:2: note:   template argument deduction/substitution failed:
main.cpp:22:28: note:   cannot convert ‘i’ (type ‘int’) to type ‘std::map::const_iterator {aka std::_Rb_tree_const_iterator >}’
     mp.insert(i, new NODE());
                            ^
In file included from /usr/include/c++/7/map:61:0,
                 from main.cpp:10:
/usr/include/c++/7/bits/stl_map.h:885:2: note: candidate: template void std::map<_Key, _Tp, _Compare, _Alloc>::insert(_InputIterator, _InputIterator) [with _InputIterator = _InputIterator; _Key = int; _Tp = NODE*; _Compare = std::less; _Alloc = std::allocator >]
  insert(_InputIterator __first, _InputIterator __last)
  ^~~~~~
/usr/include/c++/7/bits/stl_map.h:885:2: note:   template argument deduction/substitution failed:
main.cpp:22:28: note:   deduced conflicting types for parameter ‘_InputIterator’ (‘int’ and ‘NODE*’)
     mp.insert(i, new NODE());

person J. Snow    schedule 16.05.2020    source источник
comment
mp[i]=новый узел();   -  person Igor R.    schedule 16.05.2020
comment
нет перегрузки insert для передаваемых вами аргументов, см. здесь en.cppreference. com/w/cpp/контейнер/карта/вставка   -  person 463035818_is_not_a_number    schedule 16.05.2020
comment
Пожалуйста, прочтите данную ссылку. Вы просто пытаетесь использовать несуществующий интерфейс. Таким образом, вы должны передать правильные аргументы существующему интерфейсу. insert можно вызывать с std::pair, но не с двумя отдельными параметрами. {} в этом случае аргументы неявно преобразуются в std::pair.   -  person Klaus    schedule 16.05.2020


Ответы (4)


Если вы используете C++11 или более позднюю версию (что по умолчанию имеет место в последнем компиляторе), вы можете использовать map::emplace. С помощью emplace вы можете просто передать два аргумента, которые составляют обе части пары, например:

#include <iostream>
#include <string>
#include <map>

int main() {
    std::map<int, std::string> m;
    m.emplace(123, "ddd");
    for (const auto &p : m) {
        std::cout << p.first << " => " << p.second << '\n';
    }
}

Посмотрите это на Godbolt.

Заметки:

  • Я заменил NODE на std::string в своем примере, чтобы вы могли видеть, как он печатается.
  • Если вы используете C++17 или более позднюю версию, вы можете предпочесть map::try_emplace() вместо этого.
person einpoklum    schedule 16.05.2020

Если вы хотите вставить его на карту, вы должны вставить его как std::pair следующим образом:

mp.insert(std::pair<int, NODE*>(i, new NODE()));
person Tobias    schedule 16.05.2020
comment
Спасибо. Заставляет меня задаться вопросом, что мешает компилятору сделать очевидное, то есть посмотреть, составляют ли входные данные действительную пару или нет. - person J. Snow; 16.05.2020
comment
@J.Snow: Потому что разрешение перегрузки и так достаточно сложное, а слишком умный компилятор наполовину не будет улучшением. (Для компилятора может иметь смысл попытаться угадать, какую функцию вы хотели вызвать, при выводе сообщения об ошибке, но в любом случае это довольно сложно.) - person Davis Herring; 17.05.2020

ааа ок.

Так что функция вставки ожидает пару.

/usr/include/c++/7/bits/stl_map.h:802:7: note:   candidate expects 1 argument, 2 provided
/usr/include/c++/7/bits/stl_map.h:808:2: note: candidate: template std::__enable_if_t, _Pair>::value, std::pair, std::_Select1st >, _Compare, typename __gnu_cxx::__alloc_traits<_Alloc>::rebind >::other>::iterator, bool> > std::map<_Key, _Tp, _Compare, _Alloc>::insert(_Pair&&) [with _Pair = _Pair; _Key = int; _Tp = NODE*; _Compare = std::less; _Alloc = std::allocator >]
  insert(_Pair&& __x)

Спасибо за предложения выше.

  mp.insert(std::make_pair(i, p));
person J. Snow    schedule 16.05.2020

Если вы хотите вставить элемент в std::map, вы можете использовать метод emplace ( https://www.cplusplus.com/reference/map/map/emplace/ ), передавая параметры конструктора std::make_pair непосредственно ему.

#include <iostream>
#include <map>
using namespace std;

typedef struct 
{
}NODE;


int main()
{
    std::map<int, NODE*> mp;
    int i = 0;
    mp.emplace(i, new NODE());

    return 0;
}
person Andrea Pollini    schedule 16.05.2020