Question

I have a templated class called PooledResource. It handles loading things like textures and sounds for me and ensures that I don't load the same one multiple times on accident. Resources of a certain type will always be in a certain subdirectory, and I wanted to make it easier to load them, so I decided to add a static variable that keeps track of the root folder for a certain type of resource.

template <typename T>
class PooledResource
{
public:
    // ...

    static const char* PathPrefix;
    static ResourceTable myResourceTable;


    static void load(const char* filename)
    {
        // Any attempt to use PathPrefix in here causes a compilation error
        // All I want to do is use PathPrefix and filename to get the full
        // path do a file and load it. 
    }
};

template <typename T>
const char* PooledResource<T>::PathPrefix = NULL;

template <typename T>
typename PooledResource<T>::ResourceTable PooledResource<T>::myResourceTable;

The idea is that I can use a typedef'd version of this for various types. For example, in PooledTexture.hpp I would have:

typedef PooledResource<Texture> PooledTexture;

and in PooledTexture.cpp I would have:

template <>
const char* PooledTexture::PathPrefix = "../assets/textures/";

This will all compile and run fine if I don't attempt to use PathPrefix in the load function above. As soon as I use it though, I get errors like this:

 90 || CMakeFiles/game.dir/PooledTexture.cpp.o:(.data+0x0): multiple definition of `ag::PooledResource<sf::Texture>::PathPrefix'
 91 CMakeFiles/game.dir/lua/LuaFrame.cpp.o:/usr/include/c++/4.6/i686-linux-gnu/./bits/gthr-default.h|241| first defined here

I've tried reproducing this with a simpler case to try to hunt down the problem, but other cases I try seem to work. I'm not sure what I'm doing differently here that would cause this error.

Was it helpful?

Solution

The problem here is that your space for the variable is allocated in the header, which is then included by multiple compilation units - LuaFrame.cpp.o and PooledTexture.cpp.o. Side note: naming your object files .cpp.o is confusing.

So, there are two variables with the same name.

You need to move the actual space allocation (not the declaration, but the bit where you assign it) into a cpp file instead of a header, and then build that file in with the rest of your application. Yes, you have it in a header now: the bit where you set it to NULL!

EDIT: when you do this, the header will no longer have enough information to create an instance of the template, so you'll have to explicitly instantiate the class for each type with which you wish to use it.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top