0

I'm in a process of implementing loadAsset method in my asset manager implementation. I've tried using variadic arguments template method with following signature:

class AssetManager {
public:
   template <typename AssetType, typename... Args>
   void loadAsset(std::string_view name, const Args &...args);
...
};

And following specialization in .cpp file:

template <>
void AssetManager::loadAsset<Texture, std::string>(std::string_view name, const std::string &path) {...}

template void AssetManager::loadAsset<Texture, std::string>(std::string_view, const std::string &path); //explicit instantiation

However when trying to invoke loadAsset method like so:

m_assetManager->loadAsset<NOX::Texture>("texture", "assets/textures/texture.jpg");

I get the following error:

error LNK2019: unresolved external symbol "public: void __cdecl NOX::AssetManager::loadAsset<class NOX::Texture,char [28]>(class std::basic_string_view<char,struct std::char_traits<char> >,char const (&)[28])" (??$loadAsset@VTexture@NOX@@$$BY0BM@D@AssetManager@NOX@@QEAAXV?$basic_string_view@DU?$char_traits@D@std@@@std@@AEAY0BM@$$CBD@Z) referenced in function "public: __cdecl ExampleApplication::ExampleApplication(struct NOX::ApplicationSpecification const &)" (??0ExampleApplication@@QEAA@AEBUApplicationSpecification@NOX@@@Z)

How can I prevent that from happening? I'm using C++17 and can't use C++20.

1 Answers1

0

If you specialize a template in a cpp file, that'll be available in the given file, but not externally (unless, of course, if you instantiate it manually). Best way to do it is to move all template definitions to header.

lorro
  • 10,687
  • 23
  • 36
  • I get `fatal error LNK1169: one or more multiply defined symbols found` – RafalMaziejuk Oct 08 '22 at 17:45
  • Managed to fix it. Is it possible to define those specializations in `.cpp` file? – RafalMaziejuk Oct 08 '22 at 17:50
  • @RafalMaziejuk Yes, but then you need to instantiate for each usage (similarly for non-template declaration). In sort, it's usually not worth it, with the exception being when you only use it locally or only use it for a given (very small) set of arguments. – lorro Oct 08 '22 at 18:28
  • Do you know how can I specialize `loadAsset` method with std::string_view/std::string? I've tried the following specialization: `void loadAsset(std::string_view name, std::string_view path)` and it is called like so: `m_assetManager->loadAsset("fullscreenTexture", "assets/shaders/shader.glsl");` but it doesn't seem to recognize it. – RafalMaziejuk Oct 08 '22 at 19:06
  • If I were to write this specialization like so: `void loadAsset(std::string_view name, const char * path)` It would be recognized. – RafalMaziejuk Oct 08 '22 at 19:08