Skip to main content
GameDev.net gamedev.net
🔒 Locked

Cast std::mapstd::string, foo to std::mapstd::string, bar

Started by EnigmaticCoder Nov 30, 2009 at 5:41 PM 16 replies 2.2k views
Original Post
EnigmaticCoder
EnigmaticCoder
I have a class called foo and a class called bar which inherits from foo. I create an std::map and want to cast it to an std::map. How can I do this in C++ without using the boost library? [Edited by - EnigmaticCoder on November 30, 2009 6:00:14 PM]
--------------------Enigmatic Coding
nullsquared
nullsquared
I don't believe anything in boost can help with this - do you have some kind of general fear of boost that you mentioned it? [grin]

Also, you can't cast like that. Closest to it would be to iterate over the first map and duplicate it in the second map, except if you're not using pointers then you'll get slicing.
EnigmaticCoder
EnigmaticCoder
Quote:
Original post by nullsquared
I don't believe anything in boost can help with this - do you have some kind of general fear of boost that you mentioned it? [grin]


While I do have a fear of boost, I'm not using it for another reason: it hasn't been ported to the Dreamcast.
--------------------Enigmatic Coding
nullsquared
nullsquared
Quote:
Original post by EnigmaticCoder
While I do have a fear of boost, I'm not using it for another reason: it hasn't been ported to the Dreamcast.


Sounds like a valid reason. Just thought it was a bit funny the way you randomly mentioned boost [lol].
Sneftel
Sneftel
Quote:
Original post by EnigmaticCoder
I have a class called foo and a class called bar which inherits from foo. I create an std::map and want to cast it to an std::map.
No you don't. If you could cast it to a map, then you could insert a foo which wasn't a bar into it, which would of course break things. What are you trying to do with this?
EnigmaticCoder
EnigmaticCoder
I'm trying to make a generic DrawSprites function that works for players, enemies, and bullets.
--------------------Enigmatic Coding
Sneftel
Sneftel
Have DrawSprites templated on the container type, or pass in an iterator pair and have it templated on the iterator type.
EnigmaticCoder
EnigmaticCoder
Now I'm getting a couple of errors:

`it' was not declared in this scope

template <class T>std::string Sprite::checkSpriteCollisions(std::map<const std::string, T> sprites){	float otherSpriteX;	float otherSpriteY;	float otherSpriteZ;	float otherSpriteWidth;	float otherSpriteHeight;        //Error here	for (std::map<const std::string, T>::iterator it = sprites.begin();			it != sprites.end(); ++it)	{		if (it->second == *this)			continue;		it->second.getCoordinates(otherSpriteX, otherSpriteY, otherSpriteZ);		it->second.getDimensions(otherSpriteWidth, otherSpriteHeight);		BoundingBox b1(x, y, x + width, y + height);		BoundingBox b2(otherSpriteX, otherSpriteY,				otherSpriteX + otherSpriteWidth,				otherSpriteY + otherSpriteHeight);		if (RectangularCollisionDetection(b1, b2))						return it->first;	}	return NO_SPRITE;}
--------------------Enigmatic Coding
nullsquared
nullsquared
Insert typename in front of the fully-qualified name.

Since T is templated, the compiler cannot figure out whether map<..., T>::iterator is a type or a constant, therefore you need to manually tell it that (by using typename).
EnigmaticCoder
EnigmaticCoder
Like this?

template <typename T>void drawSprites(std::map<const std::string, pvr_ptr_t> images,		std::map<const std::string, T> sprites){	for (typename std::map<std::string, T>::iterator it = sprites.begin(); it != sprites.end(); ++it)    {    	float x;    	float y;    	float z;    	float width;    	float height;    	it->second.getCoordinates(x, y, z);    	it->second.getDimensions(width, height);    	drawImage(images[it->second.getImagePath()], x, y, z, width, height);    }}


EDIT: That doesn't look right at all.
--------------------Enigmatic Coding
nullsquared
nullsquared
Quote:
Original post by EnigmaticCoder
Yes, but now it's not making it inside the loop.


Any more details? What do you mean "not making it inside the loop?"

Also, I take it you're compiling with GCC? I know MSVC has an extension that would allow the code to compile without typename (but that's incorrect according to the language itself).
EnigmaticCoder
EnigmaticCoder
Erm, actually it's in a similar function. My spaceships aren't being draw, so I figured it wasn't iterating. In the code below "Outside loop" is printed, but "inside loop" is not:

template <typename T>void drawSprites(std::map<const std::string, pvr_ptr_t> images,		std::map<const std::string, T> sprites){	dbglog(DBG_DEBUG, "Outside loop\t");	for (typename std::map<std::string, T>::iterator it = sprites.begin(); it != sprites.end(); ++it)    {    	float x;    	float y;    	float z;    	float width;    	float height;    	dbglog(DBG_DEBUG, "inside loop\t");    	it->second.getCoordinates(x, y, z);    	it->second.getDimensions(width, height);    	drawImage(images[it->second.getImagePath()], x, y, z, width, height);    }}


EDIT: Oh yeah, I am using GCC.
--------------------Enigmatic Coding
nullsquared
nullsquared
Well this has nothing to do with typename (compiler error), it's a logical error. Is sprites.empty()? There's no reason for the loop to not run unless your container is empty. Also, you're passing those maps by value (copying them every time you call that function). On top of that, unless T is a smart pointer, the sprites themselves are also getting copied when the map is copied.
littlekid
littlekid
hi would it help if you made a base class that have a draw method which is virtual, then have those concrete objects inherit from it and modify the draw method if necessary?? something like

class IDrawableObject{public:     virtual void Draw();     {        //do generic draw here, if needed override for        //specialize drawing     }};class Human : public IDrawableObject{};class Monster : public IDrawableObject{};std::list<std::tr1::weak_ptr<IDrawableObject> > drawableObjects;class HumanMgr{    std::map<std::string, std::tr1::shared_ptr<Human> > humanObjectspublic:    void InsertHuman(std::string uniqueName)    {       result = humanObjects.insert(makePair(uniqueName,           std::tr1::shared_ptr<Human>(new Human));       drawableObjects.push_back(result.first->second);    }    void RemoveHuman(std::string uniqueName)    {        humanObjects.erase(uniqueName);    }}void DrawEverything{    //iterate the drawableObjects and draw it    //if the weak_ptr is dead then remove it from list    //possibly use std::list::remove_if()}


would this work?? I am not sure too just giving my 2 cents of opinion.

Topic Locked

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

Sign in to reply to this topic.