Skip to main content
gamedev.net
🔒 Locked

std::map and calling an object's function

Started by baconfish Feb 28, 2007 at 11:11 AM 8 replies 2.8k views
Original Post
baconfish
baconfish
In the following diagram I'm trying to call a member function of a GLSpriteBase object which is stored in a std::map. (The important part is just that line of code in the middle, I just wanted to point out what everthing actually is to help explain the situation).
std::map<std::string, GLSpriteBase>
   |
   |  std::string      GLSprite *
   |      |             /
   v      v            v  
sprites[name].addUser(spr);
                ^
                |
   GLSpriteBase::adduser(GLSprite *)
But g++ vomits a really nasty stl-wtf kind of error when I'm trying to compile.
/usr/lib/gcc/i486-linux-gnu/4.1.2/../../../../include/c++/4.1.2/bits/stl_map.h:
In member function '_Tp& std::map<_Key, _Tp, _Compare, _Alloc>::operator[]
(const _Key&) [with _Key = std::basic_string<char, std::char_traits<char>,
std::allocator<char> >, _Tp = GLSpriteBase, _Compare =
std::less<std::basic_string<char, std::char_traits<char>, std::allocator<char>
> >, _Alloc = std::allocator<std::pair<const std::basic_string<char,
std::char_traits<char>, std::allocator<char> >, GLSpriteBase> >]':
glsprite.cpp:105:   instantiated from here
/usr/lib/gcc/i486-linux-gnu/4.1.2/../../../../include/c++/4.1.2/bits/
stl_map.h:348: error: no matching function for call to
'GLSpriteBase::GLSpriteBase()'
glsprite.cpp:16: note: candidates are: GLSpriteBase::GLSpriteBase(std::string)
glsprite.hpp:48: note:                 GLSpriteBase::GLSpriteBase(const
GLSpriteBase&)

I'm not even sure what to make of this. Why does it think I want to use the constructor? I think the problem has something to do with me trying to use "sprites[name]" and calling a function in the object it gives me, but I've done the same kind of thing before without a problem. Any ideas? If you need more details let me know, I didn't want to paste too much junk up front, especially with the error messages.
Ok.
ToohrVyk
ToohrVyk
Simple: if there is no GLSpriteBase associated to name in sprites, operator[] will create a new one using the default constructor. The compiler error is complaining that no such constructor could be found.
NotAYakk
NotAYakk
To understand STL errors, you have to match up wakas and brackets.

Ie, turn this:
/usr/lib/gcc/i486-linux-gnu/4.1.2/../../../../include/c++/4.1.2/bits/stl_map.h:In member function '_Tp& std::map<_Key, _Tp, _Compare, _Alloc>::operator[](const _Key&) [with _Key = std::basic_string<char, std::char_traits<char>,std::allocator<char> >, _Tp = GLSpriteBase, _Compare =std::less<std::basic_string<char, std::char_traits<char>, std::allocator<char>> >, _Alloc = std::allocator<std::pair<const std::basic_string<char,std::char_traits<char>, std::allocator<char> >, GLSpriteBase> >]':glsprite.cpp:105:   instantiated from here/usr/lib/gcc/i486-linux-gnu/4.1.2/../../../../include/c++/4.1.2/bits/stl_map.h:348: error: no matching function for call to'GLSpriteBase::GLSpriteBase()'glsprite.cpp:16: note: candidates are: GLSpriteBase::GLSpriteBase(std::string)glsprite.hpp:48: note:                 GLSpriteBase::GLSpriteBase(constGLSpriteBase&)


into this:
/usr/lib/gcc/i486-linux-gnu/4.1.2/../../../../include/c++/4.1.2/bits/stl_map.h:In member function '  _Tp& std::map<    _Key, _Tp, _Compare, _Alloc  >::operator[] (const _Key&) [    with _Key = std::basic_string<      char, std::char_traits<char>, std::allocator<char>    >,    _Tp = GLSpriteBase,    _Compare = std::less<      std::basic_string<char, std::char_traits<char>, std::allocator<char> >    >,    _Alloc = std::allocator<      std::pair<        const std::basic_string<char, std::char_traits<char>, std::allocator<char> >,        GLSpriteBase      >    >  ]':glsprite.cpp:105:instantiated from here /usr/lib/gcc/i486-linux-gnu/4.1.2/../../../../include/c++/4.1.2/bits/stl_map.h:348:error: no matching function for call to'GLSpriteBase::GLSpriteBase()'glsprite.cpp:16: note: candidates are: GLSpriteBase::GLSpriteBase(std::string)glsprite.hpp:48: note:                 GLSpriteBase::GLSpriteBase(const GLSpriteBase&)


And all of a sudden, the STL template spam at the front can be parsed.

As noted, the STL template spam actually doesn't contain the useful stuff -- the useful stuff is the last few lines.

operator[] on maps is "create if you don't find it". If you don't want that semantics, you should use find to search for the element and get an iterator, then check for the end.

I believe "at" might be a different alternative, if you to deal with exceptions.
baconfish
baconfish
But... but... damnit.

I'm beginning to think I had this very same problem the other time I used similar code; looking back I see an empty default constructor with the comment "does nothing"...

Thanks ToohrVyk.
EDIT: Thanks to you too NotAYakk

Before I'm using the addUser() function I check to make sure that the GLSpriteBase I want is indeed in the map already so I'm making sure that it will never create one using the default constructor there. I guess I could write this better using an iterator since I'm using find anyways.

Thanks again.
Ok.
ToohrVyk
ToohrVyk
Quote:
Original post by NotAYakk
I believe "at" might be a different alternative, if you to deal with exceptions.


Actually, it's find, and it returns an invalid iterator on failure.

baconfish
baconfish
Wait... would it be possible to specify which constructor it should use in case it's not already in the map?
Ok.
ToohrVyk
ToohrVyk
Quote:
Original post by Stukkm
Wait... would it be possible to specify which constructor it should use in case it's not already in the map?


No. operator[] always uses the default constructor. However, you can create your own access function for the map, which uses find and insert to insert the correct object in the map if it isn't found.
Bregma
Bregma
Quote:
Original post by ToohrVyk
Quote:
Original post by NotAYakk
I believe "at" might be a different alternative, if you to deal with exceptions.


Actually, it's find, and it returns an invalid iterator on failure.


Actually, it returns the completely valid iterator equal to map::end() if no such key is found ([23.1.2] table 69). Just because the iterator is not dereferencable does not make it invalid.

--smw
Stephen M. Webb
Professional Free Software Developer
ToohrVyk
ToohrVyk
Quote:
Original post by Bregma
Just because the iterator is not dereferencable does not make it invalid.


You're right, my semantics were sloppy.

NotAYakk
NotAYakk
*nod* -- at was a std::vector member, not a std::map member (and my custom map class member...)

mea culpa!

Topic Locked

This topic has been locked by a moderator. New replies are not allowed.

Sign in to reply to this topic.