Explicit specialization of function templates causes linker error

Functions.h:

#pragma once #include <iostream> template<class T> void TemplatedFunction(T* p) {} template<> void TemplatedFunction<float>(float* p) {} template<> void TemplatedFunction<char>(char* p) {} 

Functions.cpp:

 #include "Functions.h" void Test() { TemplatedFunction<float>(NULL); TemplatedFunction<char>(NULL); } 

main.cpp:

 #include "Functions.h" void Test(); int main() { Test(); return 0; } 

Build Errors:

 main.obj : error LNK2005: "void __cdecl TemplatedFunction<float>(float *)" ( ??$TemplatedFunction@M @@ YAXPAM@Z ) already defined in Functions.obj main.obj : error LNK2005: "void __cdecl TemplatedFunction<char>(char *)" ( ??$TemplatedFunction@D @@ YAXPAD@Z ) already defined in Functions.obj 

I know two ways to fix this:

  • Do not include Functions.h in several .cpp files - cannot be used in a complex project if the h file contains some additional definitions needed in many .cpp files.

  • Declare all template functions as static . But this means that specialized functions are displayed in all .cpp files where .h functions are included, even if they are not used, which can lead to code duplication.

So, I see that a specialized template function behaves like a non-template function. Is there any other solution to prevent linker error without static declaration? If functions are declared static , does the modern C ++ compiler make them from an optimized assembly if they are not used?

Edit After reading the first two answers: I am not asking here how to prevent such a linker error. Assuming I can't move the specialization to a .cpp file and leave it in the .h file using static or inline , does this cause duplication and bloat code in an optimized assembly when these functions are added to every .cpp file, where the .h file included even if they are not used?

+6
source share
2 answers

So, I see that a specialized template function behaves like a non-template function.

Right.

Is there any other solution to prevent linker error without static declaration?

Yes, like any normal function without a template:

Or Define function specializations as inline

or Declare (but not define) specializations in the header:

 template<> void TemplatedFunction<float>(float* p); template<> void TemplatedFunction<char>(char* p); 

and define them in Functions.cpp

 template<> void TemplatedFunction<float>(float* p) {} template<> void TemplatedFunction<char>(char* p) {} 

These are more efficient options than using static , because when creating static functions, there are other side effects, such as assigning functions to different addresses in each translation unit and changing local static variables in each translation unit. This is a semantic change, not just a solution to a linker error.

If functions are declared static , does the modern C ++ compiler make them remove from the optimized assembly if they are not used?

Yes. But in any files where they are used, you will get a duplicate of the code, making the executable larger than if there was one function definition.

Assuming I can't move the specialization to a .cpp file and leave it in a .h file using static ...

I see no good reason why this is necessary, but in any case ...

... or inline , does this cause duplication and bloat of code in an optimized assembly when these functions are added to every .cpp file that includes the .h file, even if they are not used?

No, if they are not used in the given file, they will not affect the size of the object compiled from this file.

Your question is misleading because it seems to be about templates (the heading is very clear about templates!), But whether the unused built-in / static functions are the reason for the bloat of the code depends on whether the functions are templates or not.

If your question is simply "do not use unused built-in and static functions that affect the size of the object?" the answer is no, both for ordinary functions and for functional templates.

+14
source

Such explicit specializations should be transferred to a .cpp file or made inline . The compiler will find them there. If you define them in the header, you will get β€œalready defined” error messages, just like you will get them for the usual non-built-in and non-static functions defined in the header included in several compilation units.

+2
source

Source: https://habr.com/ru/post/1201235/


All Articles