std::map unable to insert objects

Started by
3 comments, last by rip-off 13 years, 3 months ago
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]
Electronic Meteor - My experiences with XNA and game development
Advertisement
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
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.
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.
Electronic Meteor - My experiences with XNA and game development
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.

This topic is closed to new replies.

Advertisement