(Final question at the bottom)
Recently, I asked a question concerning how I would fix linker errors (on duplicate symbols concerning multiple definitions of a template void.
Because I was using the functions in multiple source files, I was suggested to use the keyword inline
to allow declarations in the header or put the declarations in a compiled source file.
After I realized that inline
had some bad repercussions, I put my declarations in a source file.
Now this was okay, except for variadic templates:
template<typename T, typename... Args>
void cleanup(T *t, Args&&... args);
I found some apparent solutions - but not to variadic templates - use a .tpp file (but it started declaring duplicate symbols again) or keep the source file and add explicit instantiations.
But void cleanup
has the potential to be used hundreds of combinations of parameters, so I don't want to explicitly instantiate everything.
Question: So, how would I go about either
inline
?Examples of duplicate/undefined symbol errors for .tpp declaration and putting the above template definition in a source file respectively.
duplicate symbol __Z7cleanupI10SDL_WindowJEEvPT_DpOT0_ in:
CMakeFiles/Game.dir/Game/main.cc.o
CMakeFiles/Game.dir/Game/RichTools/rtexture.cc.o
_
Undefined symbols for architecture x86_64:
"void cleanup<SDL_Renderer, SDL_Window*&>(SDL_Renderer*, SDL_Window*&&&)",
referenced from:
cleanQuit() in main.cpp.o
ld: symbol(s) not found for architecture x86_64
The advice in answer to your first question: to make inline or move to source file was only about your fully specialized functions - these with empty parameter list template <>
.
So, do that:
Your header file:
// This shall be in header - it is not full specialization:
template<typename T, typename... Args>
void cleanup(T *t, Args&&... args){
//Cleanup the first item in the list
cleanup(t);
//Recurse to clean up the remaining arguments
cleanup(std::forward<Args>(args)...);
}
// These shall be only declared here, and implemented in source file,
// treat fully specialized function templates as regular functions
template<>
void cleanup<SDL_Window>(SDL_Window *win);
template<>
void cleanup<SDL_Renderer>(SDL_Renderer *ren);
template<>
void cleanup<SDL_Texture>(SDL_Texture *tex);
Your source file:
template<>
void cleanup<SDL_Window>(SDL_Window *win){
if (!win){
return;
}
SDL_DestroyWindow(win);
}
template<>
void cleanup<SDL_Renderer>(SDL_Renderer *ren){
if (!ren){
return;
}
SDL_DestroyRenderer(ren);
}
template<>
void cleanup<SDL_Texture>(SDL_Texture *tex){
if (!tex){
return;
}
SDL_DestroyTexture(tex);
}
template<>
void cleanup<SDL_Surface>(SDL_Surface *surf){
if (!surf){
return;
}
SDL_FreeSurface(surf);
}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With