• 12
• 10
• 10
• 13
• 10

Template functions not being generated

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

Recommended Posts

I have a Resource Manager class, which uses template functions to return shaders and materials. Here is the function for materials (the shader one is pretty much identical):

template <typename T> T* ResourceManager::getMaterial(std::string name) { using rendering::MaterialBase; MaterialBase* material; if (m_materials.exists(name)) material = m_materials.getPointerToElement(name); else { std::string message = "Could not find material: " + name; MessageBox(0, message.c_str(), "Material load Fail", MB_OK); return 0; } #if defined( DEBUG ) || defined( _DEBUG ) T* returnedMaterial = dynamic_cast<T*>(material); if (!returnedMaterial) { std::string message = "Tried to cast Material " + name + " to invalid type"; MessageBox(0, message.c_str(), "Material load Fail", MB_OK); } return returnedMaterial; #else return static_cast<T*>(material); #endif }

I set up my materials during the resourceManager's initialisation, and using this function, I can get a pointer to a material using (for example) getMaterial<Lit_DiffuseTex>("WoodenPlanks");
Using a template lets me cast the base material class to the appropriate type before returning it.

The problem is that I get unresolved external errors when I try to use it from any other class other than from the ResourceManager, as if the compiler isn't generating the appropriate functions from the template. What's more, if I call the getMaterial function with a given typename from within the ResourceManager first, I don't get these errors anywhere - if I put a call to getMaterial<Lit_DiffuseTex>("WoodenPlanks") in the ResourceManager's initialisation routine and just don't use the returned material, I can then call the function using the same typename from anywhere and it works fine.

One thing, I'm trying to call this from a different namespace than that used by the ResourceManager, could that be causing it?

I suppose if all else fails, I could ditch the template and have it return the base class, and have the calling object deal with casting, but it would be nice to keep the slightly messy casting in one place.

Share on other sites
Well, for starters, you have to have the full template available at the point of use. So, in some header that is included by all your files that need the getMaterial, you need to have
 template <typename T> T* ResourceManager::getMaterial(std::string name) { //... } 
You can't just have the function declaration in the header, and the definition in some cpp. Templates don't work like normal functions in that regard.

Share on other sites
Aaahh, that was it! I forgot you can't split templates up between files.

Thanks