Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Why the code using std::map can not compile?

I am trying to use std::map. but I face a compile problem. The code:

// main.cpp
#include <iostream>
#include <map>

class Student
{
public:
    // with follow line there will be no compile error
    // explicit Student(){}

    explicit Student(std::string name_, int grade_)
        : name(name_), grade(grade_)
    {
    }

    ~Student()
    {
    }

private:
    std::string name;
    int grade;
};

int main(int argc, char **argv)
{
    std::map<std::string, Student> student_map;
    Student x("mike", 10);
    student_map.insert(std::pair<std::string, Student>("mike", x));
    Student y = student_map["mike"];
    return 0;
}

I am using g++ to compile the code

g++ main.cpp

However the compiler said that

In file included from /usr/include/c++/7/bits/stl_map.h:63:0,
                 from /usr/include/c++/7/map:61,
                 from main.cpp:2:
/usr/include/c++/7/tuple: In instantiation of ‘std::pair<_T1, _T2>::pair(std::tuple<_Args1 ...>&, std::tuple<_Args2 ...>&, std::_Index_tuple<_Indexes1 ...>, std::_Index_tuple<_Indexes2 ...>) [with _Args1 = {std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >&&}; long unsigned int ..._Indexes1 = {0}; _Args2 = {}; long unsigned int ..._Indexes2 = {}; _T1 = const std::__cxx11::basic_string<char>; _T2 = Student]’:
/usr/include/c++/7/tuple:1641:63:   required from ‘std::pair<_T1, _T2>::pair(std::piecewise_construct_t, std::tuple<_Args1 ...>, std::tuple<_Args2 ...>) [with _Args1 = {std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >&&}; _Args2 = {}; _T1 = const std::__cxx11::basic_string<char>; _T2 = Student]’
/usr/include/c++/7/ext/new_allocator.h:136:4:   required from ‘void __gnu_cxx::new_allocator<_Tp>::construct(_Up*, _Args&& ...) [with _Up = std::pair<const std::__cxx11::basic_string<char>, Student>; _Args = {const std::piecewise_construct_t&, std::tuple<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >&&>, std::tuple<>}; _Tp = std::_Rb_tree_node<std::pair<const std::__cxx11::basic_string<char>, Student> >]’
/usr/include/c++/7/bits/alloc_traits.h:475:4:   required from ‘static void std::allocator_traits<std::allocator<_CharT> >::construct(std::allocator_traits<std::allocator<_CharT> >::allocator_type&, _Up*, _Args&& ...) [with _Up = std::pair<const std::__cxx11::basic_string<char>, Student>; _Args = {const std::piecewise_construct_t&, std::tuple<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >&&>, std::tuple<>}; _Tp = std::_Rb_tree_node<std::pair<const std::__cxx11::basic_string<char>, Student> >; std::allocator_traits<std::allocator<_CharT> >::allocator_type = std::allocator<std::_Rb_tree_node<std::pair<const std::__cxx11::basic_string<char>, Student> > >]’
/usr/include/c++/7/bits/stl_tree.h:626:32:   required from ‘void std::_Rb_tree<_Key, _Val, _KeyOfValue, _Compare, _Alloc>::_M_construct_node(std::_Rb_tree<_Key, _Val, _KeyOfValue, _Compare, _Alloc>::_Link_type, _Args&& ...) [with _Args = {const std::piecewise_construct_t&, std::tuple<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >&&>, std::tuple<>}; _Key = std::__cxx11::basic_string<char>; _Val = std::pair<const std::__cxx11::basic_string<char>, Student>; _KeyOfValue = std::_Select1st<std::pair<const std::__cxx11::basic_string<char>, Student> >; _Compare = std::less<std::__cxx11::basic_string<char> >; _Alloc = std::allocator<std::pair<const std::__cxx11::basic_string<char>, Student> >; std::_Rb_tree<_Key, _Val, _KeyOfValue, _Compare, _Alloc>::_Link_type = std::_Rb_tree_node<std::pair<const std::__cxx11::basic_string<char>, Student> >*]’
/usr/include/c++/7/bits/stl_tree.h:643:21:   required from ‘std::_Rb_tree_node<_Val>* std::_Rb_tree<_Key, _Val, _KeyOfValue, _Compare, _Alloc>::_M_create_node(_Args&& ...) [with _Args = {const std::piecewise_construct_t&, std::tuple<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >&&>, std::tuple<>}; _Key = std::__cxx11::basic_string<char>; _Val = std::pair<const std::__cxx11::basic_string<char>, Student>; _KeyOfValue = std::_Select1st<std::pair<const std::__cxx11::basic_string<char>, Student> >; _Compare = std::less<std::__cxx11::basic_string<char> >; _Alloc = std::allocator<std::pair<const std::__cxx11::basic_string<char>, Student> >; std::_Rb_tree<_Key, _Val, _KeyOfValue, _Compare, _Alloc>::_Link_type = std::_Rb_tree_node<std::pair<const std::__cxx11::basic_string<char>, Student> >*]’
/usr/include/c++/7/bits/stl_tree.h:2398:33:   required from ‘std::_Rb_tree<_Key, _Val, _KeyOfValue, _Compare, _Alloc>::iterator std::_Rb_tree<_Key, _Val, _KeyOfValue, _Compare, _Alloc>::_M_emplace_hint_unique(std::_Rb_tree<_Key, _Val, _KeyOfValue, _Compare, _Alloc>::const_iterator, _Args&& ...) [with _Args = {const std::piecewise_construct_t&, std::tuple<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >&&>, std::tuple<>}; _Key = std::__cxx11::basic_string<char>; _Val = std::pair<const std::__cxx11::basic_string<char>, Student>; _KeyOfValue = std::_Select1st<std::pair<const std::__cxx11::basic_string<char>, Student> >; _Compare = std::less<std::__cxx11::basic_string<char> >; _Alloc = std::allocator<std::pair<const std::__cxx11::basic_string<char>, Student> >; std::_Rb_tree<_Key, _Val, _KeyOfValue, _Compare, _Alloc>::iterator = std::_Rb_tree_iterator<std::pair<const std::__cxx11::basic_string<char>, Student> >; std::_Rb_tree<_Key, _Val, _KeyOfValue, _Compare, _Alloc>::const_iterator = std::_Rb_tree_const_iterator<std::pair<const std::__cxx11::basic_string<char>, Student> >]’
/usr/include/c++/7/bits/stl_map.h:512:8:   required from ‘std::map<_Key, _Tp, _Compare, _Alloc>::mapped_type& std::map<_Key, _Tp, _Compare, _Alloc>::operator[](std::map<_Key, _Tp, _Compare, _Alloc>::key_type&&) [with _Key = std::__cxx11::basic_string<char>; _Tp = Student; _Compare = std::less<std::__cxx11::basic_string<char> >; _Alloc = std::allocator<std::pair<const std::__cxx11::basic_string<char>, Student> >; std::map<_Key, _Tp, _Compare, _Alloc>::mapped_type = Student; std::map<_Key, _Tp, _Compare, _Alloc>::key_type = std::__cxx11::basic_string<char>]’
main.cpp:29:35:   required from here
/usr/include/c++/7/tuple:1652:70: error: no matching function for call to ‘Student::Student()’
         second(std::forward<_Args2>(std::get<_Indexes2>(__tuple2))...)
                                                                      ^
main.cpp:10:14: note: candidate: Student::Student(std::__cxx11::string, int)
     explicit Student(std::string name_, int grade_)
              ^~~~~~~
main.cpp:10:14: note:   candidate expects 2 arguments, 0 provided
main.cpp:4:7: note: candidate: Student::Student(const Student&)
 class Student
       ^~~~~~~
main.cpp:4:7: note:   candidate expects 1 argument, 0 provided

There is a sentence that hide in the error that:

error: no matching function for call to ‘Student::Student()’

I try to add the empty constructor, the code can compile now.

My problem is: Why the class must have empty constructor?

Am I misunderstand anything?

like image 635
Xu Hui Avatar asked Jan 26 '23 19:01

Xu Hui


1 Answers

std::map's operator[] default-constructs a mapped_type if the key does not exist in the map.

You do not need a default constructor if instead you use map's .find

like image 52
Pubby Avatar answered Jan 31 '23 21:01

Pubby