Search code examples
c++compiler-errorsstlg++

Calling value functions of map of a custom class


I have STL map of a custom class where the key is an integer and the value is an object of my class. I want to call a function of my class using the map. My code is as follows:

#include <map>                                                                                                                                                                                                 
#include <iostream>

class myclass
{
        private:
                int x;
        public:
                myclass(int y)
                {
                        this->x = y;
                }

                int add_to_x(int y) const
                {
                        return (this->x + y); 
                }
};

int main()
{
        std::map<int, myclass> mymap;

        mymap.emplace(1, 10);
        mymap.emplace(2, 20);

        std::cout << mymap[1].add_to_x(100) << std::endl;
        std::cout << mymap[2].add_to_x(100) << std::endl;

        return 0;
}

However, which I compile this code using g++ version 11.4.0, I get the following compilation error. I'm not sure where I'm going wrong. How can I fix this?

In file included from /usr/include/c++/11/bits/stl_map.h:63,
                 from /usr/include/c++/11/map:61,
                 from test.cpp:1:
/usr/include/c++/11/tuple: In instantiation of ‘constexpr std::pair<_T1, _T2>::pair(std::tuple<_Args1 ...>&, std::tuple<_Args2 ...>&, std::_Index_tuple<_Indexes1 ...>, std::_Index_tuple<_Indexes2 ...>) [with _Args1 = {int&&}; long unsigned int ..._Indexes1 = {0}; _Args2 = {}; long unsigned int ..._Indexes2 = {}; _T1 = const int; _T2 = myclass]’:
/usr/include/c++/11/tuple:1809:63:   required from ‘constexpr std::pair<_T1, _T2>::pair(std::piecewise_construct_t, std::tuple<_Args1 ...>, std::tuple<_Args2 ...>) [with _Args1 = {int&&}; _Args2 = {}; _T1 = const int; _T2 = myclass]’
/usr/include/c++/11/bits/stl_construct.h:97:14:   required from ‘constexpr decltype (::new(void*(0)) _Tp) std::construct_at(_Tp*, _Args&& ...) [with _Tp = std::pair<const int, myclass>; _Args = {const std::piecewise_construct_t&, std::tuple<int&&>, std::tuple<>}; decltype (::new(void*(0)) _Tp) = std::pair<const int, myclass>*]’
/usr/include/c++/11/bits/alloc_traits.h:518:4:   required from ‘static constexpr void std::allocator_traits<std::allocator<_Up> >::construct(std::allocator_traits<std::allocator<_Up> >::allocator_type&, _Up*, _Args&& ...) [with _Up = std::pair<const int, myclass>; _Args = {const std::piecewise_construct_t&, std::tuple<int&&>, std::tuple<>}; _Tp = std::_Rb_tree_node<std::pair<const int, myclass> >; std::allocator_traits<std::allocator<_Up> >::allocator_type = std::allocator<std::_Rb_tree_node<std::pair<const int, myclass> > >]’
/usr/include/c++/11/bits/stl_tree.h:595: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<int&&>, std::tuple<>}; _Key = int; _Val = std::pair<const int, myclass>; _KeyOfValue = std::_Select1st<std::pair<const int, myclass> >; _Compare = std::less<int>; _Alloc = std::allocator<std::pair<const int, myclass> >; std::_Rb_tree<_Key, _Val, _KeyOfValue, _Compare, _Alloc>::_Link_type = std::_Rb_tree_node<std::pair<const int, myclass> >*]’
/usr/include/c++/11/bits/stl_tree.h:612: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<int&&>, std::tuple<>}; _Key = int; _Val = std::pair<const int, myclass>; _KeyOfValue = std::_Select1st<std::pair<const int, myclass> >; _Compare = std::less<int>; _Alloc = std::allocator<std::pair<const int, myclass> >; std::_Rb_tree<_Key, _Val, _KeyOfValue, _Compare, _Alloc>::_Link_type = std::_Rb_tree_node<std::pair<const int, myclass> >*]’
/usr/include/c++/11/bits/stl_tree.h:2431: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<int&&>, std::tuple<>}; _Key = int; _Val = std::pair<const int, myclass>; _KeyOfValue = std::_Select1st<std::pair<const int, myclass> >; _Compare = std::less<int>; _Alloc = std::allocator<std::pair<const int, myclass> >; std::_Rb_tree<_Key, _Val, _KeyOfValue, _Compare, _Alloc>::iterator = std::_Rb_tree<int, std::pair<const int, myclass>, std::_Select1st<std::pair<const int, myclass> >, std::less<int>, std::allocator<std::pair<const int, myclass> > >::iterator; std::_Rb_tree<_Key, _Val, _KeyOfValue, _Compare, _Alloc>::const_iterator = std::_Rb_tree<int, std::pair<const int, myclass>, std::_Select1st<std::pair<const int, myclass> >, std::less<int>, std::allocator<std::pair<const int, myclass> > >::const_iterator]’
/usr/include/c++/11/bits/stl_map.h:520:37:   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 = int; _Tp = myclass; _Compare = std::less<int>; _Alloc = std::allocator<std::pair<const int, myclass> >; std::map<_Key, _Tp, _Compare, _Alloc>::mapped_type = myclass; std::map<_Key, _Tp, _Compare, _Alloc>::key_type = int]’
test.cpp:27:29:   required from here
/usr/include/c++/11/tuple:1820:9: error: no matching function for call to ‘myclass::myclass()’
 1820 |         second(std::forward<_Args2>(std::get<_Indexes2>(__tuple2))...)
      |         ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
test.cpp:9:17: note: candidate: ‘myclass::myclass(int)’
    9 |                 myclass(int y)
      |                 ^~~~~~~
test.cpp:9:17: note:   candidate expects 1 argument, 0 provided
test.cpp:4:7: note: candidate: ‘constexpr myclass::myclass(const myclass&)’
    4 | class myclass
      |       ^~~~~~~
test.cpp:4:7: note:   candidate expects 1 argument, 0 provided
test.cpp:4:7: note: candidate: ‘constexpr myclass::myclass(myclass&&)’
test.cpp:4:7: note:   candidate expects 1 argument, 0 provided

As I understand it the error tells me that when I'm accessing mymap using the [] operator, it is trying to create a new object of the class myclass. However, I just want a reference to the myclass object which I've inserted into the map. How can I achieve this?


Solution

  • I figure out how to do it. It turns out the [] operator also inserts a value if one does not exist yet. Therefore it need the default constructor of the value type to be present. Therefore, if you only need to access an element and not construct it, you can use at(key). In my example converting mymap[1].add_to_x(100) to mymap.at(1).add_to_x(100) fixed the issue.