2

I have a complex map that, in the end, stores pointers to Drawable objects. Drawable objects have a draw() member function which is declared as const. I need to call all the draw functions for all objects stored in my map that are of a certain type, and I must do it inside a const function. However I can't seem to be able to preserve the const-correctness of my function (drawSolid).

My outer map (map<int, ##>) is essentially indexing some sub-maps. Sub-maps are, in turn, indexing vectors (map<ItemType, vector<##> >). Finally, this vector keeps a set of shared_ptr<Drawable> objects.

If I remove the const qualifier from my function header, everything compiles, but I need it to be const. How may I iterate through my multidimensional map, preserving const-correctness?

void DrawableItems::drawSolid(int item_list = -1) const
{
    typedef std::map<int, std::map<ItemType, std::vector<std::shared_ptr<Drawable> > > > drawablemap;
    std::vector<std::shared_ptr<Drawable> > its;
    for(drawablemap::const_iterator li = __items.begin(); li != __items.end(); li++) {
        its = li->second[SOLID];
        for(auto di = its.begin(); di != its.end(); di++) {
            di->get()->draw();
        }
    }
}

This the error I get from the compiler (G++):

/.../dss-sim/src/graphics/DrawableItems.cpp: In member function ‘void DrawableItems::drawSolid(int) const’:
/.../dss-sim/src/graphics/DrawableItems.cpp:51:35: error: passing ‘const std::map<DrawableItems::ItemType, std::vector<std::shared_ptr<Drawable> > >’ as ‘this’ argument discards qualifiers [-fpermissive]
             its = li->second[SOLID];
                                   ^
In file included from /usr/include/c++/5/map:61:0,
                 from /.../dss-sim/src/common/dss.hpp:11,
                 from /.../dss-sim/src/graphics/DrawableItems.hpp:19,
                 from /.../dss-sim/src/graphics/DrawableItems.cpp:15:
/usr/include/c++/5/bits/stl_map.h:494:7: note:   in call to ‘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 = DrawableItems::ItemType; _Tp = std::vector<std::shared_ptr<Drawable> >; _Compare = std::less<DrawableItems::ItemType>; _Alloc = std::allocator<std::pair<const DrawableItems::ItemType, std::vector<std::shared_ptr<Drawable> > > >; std::map<_Key, _Tp, _Compare, _Alloc>::mapped_type = std::vector<std::shared_ptr<Drawable> >; std::map<_Key, _Tp, _Compare, _Alloc>::key_type = DrawableItems::ItemType]’
       operator[](key_type&& __k)
Carles Araguz
  • 1,157
  • 1
  • 17
  • 37
  • 1
    Unrelated to your question and problem, but don't make your own symbols with two leading underscores, such are reserved in all scopes for the "implementation" (compiler and standard library). See [this old question and its answers](http://stackoverflow.com/questions/228783/what-are-the-rules-about-using-an-underscore-in-a-c-identifier) for more information. – Some programmer dude Jun 01 '17 at 08:58
  • What error are you getting with the const declaration? – o_weisman Jun 01 '17 at 09:08
  • I'll update the question now, but this is what I get: `/home/carles/Development/dss-sim/src/graphics/DrawableItems.cpp:51:35: error: passing ‘const std::map > >’ as ‘this’ argument discards qualifiers [-fpermissive] its = li->second[SOLID];` – Carles Araguz Jun 01 '17 at 09:08

1 Answers1

2

There is no const version of operator[] in std::map. However, there is a const version of at() which you can use instead:

its = li->second.at(SOLID);

The reason is that operator[] inserts an element if there is no element yet, so there can not be a const version of operator[].
at() on the other hand throws an exception if no element exists, and this is compatible with a const std::map.

alain
  • 11,939
  • 2
  • 31
  • 51