Sign in to follow this  

std::map unable to insert objects

This topic is 2550 days old which is more than the 365 day threshold we allow for new replies. Please post a new topic.

If you intended to correct an error in the post then please contact us.

Recommended Posts

A program I'm making uses pools of various types of resources, but only accessible to a few classes. The resource pools are contained in a single class. As such, I decided to use a static class for the resource pool and put it in as a private member for other classes that need to use it.

But I am running into a strange problem with adding resources to the pool. Each pool is represented as an std::map, and after insertion, the map still remains empty. I am guessing this has something to do with the map being inside a static class. Is this why maps don't work as intended here?

Here's my ResourcePool class with the relevant code in it.


class ResourcePool {

private:
static ResourcePool m_ResourcePool;

std::map <std::string, TextureResource> TexturePool;

public:
ResourcePool();
~ResourcePool();
static ResourcePool* Instance() { return &m_ResourcePool; }

std::map <std::string, TextureResource> Textures() { return TexturePool };
TextureResource* getTexture(std::string handle);
};





And an example of adding resources being implemented in another class.


Scene::Scene() {

// Pointer to static class
Assets = ResourcePool::Instance();
}

TextureResource* Scene::add(std::string handle, TextureResource Texture) {

Assets->Textures().insert(std::make_pair(handle, Texture));

// For debug purposes. The map still remains empty
unsigned size = Assets->Textures().size();

return Assets->getTexture(handle);
}





[Edited by - JustChris on December 23, 2010 6:12:56 PM]

Share this post


Link to post
Share on other sites
Try produce a minimum example that demonstrates the problem (or not). Here is mine:

#include <map>
#include <string>
#include <iostream>

class TextureResource { };

class ResourcePool {

private:
static ResourcePool m_ResourcePool;

public:
ResourcePool() {}
~ResourcePool() {}
static ResourcePool* Instance() { return &m_ResourcePool; }

std::map <std::string, TextureResource> Textures;
TextureResource* getTexture(std::string handle)
{
std::map<std::string, TextureResource>::iterator it = Textures.find(handle);
return it == Textures.end() ? 0 : &(it->second);
}
};

ResourcePool ResourcePool::m_ResourcePool;

class Scene {

ResourcePool *Assets;

public:

Scene();

TextureResource* add(std::string handle, TextureResource Texture);

};

Scene::Scene() {

// Pointer to static class
Assets = ResourcePool::Instance();
}

TextureResource* Scene::add(std::string handle, TextureResource Texture) {

Assets->Textures.insert(std::make_pair(handle, Texture));

// For debug purposes. The map still remains empty
unsigned size = Assets->Textures.size();
std::cout << "Assets size: " << size << '\n';
return Assets->getTexture(handle);
}

int main()
{
Scene scene;
scene.add("foo", TextureResource());
scene.add("bar", TextureResource());
}


Output:
Quote:

Assets size: 1
Assets size: 2

Share this post


Link to post
Share on other sites
Depending on when, where and how you're calling the add() function you may be running into a static initialization problem: the static object isn't actually constructed before you try using it and if you try using it before it's constructed pretty much anything can happen. You seem to want to make your ResourcePool class a singleton. If so, then you'll need to go and add all the cruft normally surrounding a singleton including making your Instance() function manually construct the singleton object if it's not already constructed. However, I'd suggest abandoning the static entirely and work with explicitly passing around instances.

Share this post


Link to post
Share on other sites
Never mind, I have found a fix. I moved the TexturePool to be a public member instead of private and have other classes access it directly.

Also about that, there was a MAJOR mistake in putting in my code in my example. It originally had the Texture pool as a public member but in my actual code it was a private member with a public accessor that didn't work. Sorry for the confusion for those that read early.

So the most likely problem was, I was passing a copy of the map and not a reference to the one in the class. But I'm sticking to just using it as a public member since I realized it wasn't so necessary to keep it private.

I will also look into making the ResourcePool class a singleton. I would only need one instance of a class, but I only want to make it accessible to a few objects.

Share this post


Link to post
Share on other sites
You don't need public members or singletons for this. Both are really good ways of ending up with unmaintainable spaghetti code in the long run. The best solution is to pass the ResourcePool directly to the classes that need it.

I generally have a few such classes I want to pass to many objects (e.g. the ResourceLoader(s), the World, the Map, and maybe some others), I wrap these in a small "Context" structure, which nearly every game object wants in its constructor.

This is a relatively clean solution, and allows easy unit testing because there is no global state.

Share this post


Link to post
Share on other sites

This topic is 2550 days old which is more than the 365 day threshold we allow for new replies. Please post a new topic.

If you intended to correct an error in the post then please contact us.

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now

Sign in to follow this