Explicit specialization of function templates causes linker error

给你一囗甜甜゛ 提交于 2019-12-17 18:55:58

问题


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:

  1. Don't include Functions.h to several .cpp files - cannot be applied in complicated project, if h-file contains some additional definitions needed in many .cpp files.

  2. Declare all templated functions as static. But this means that specialized functions appear in all .cpp files where Functions.h is included, even if they are not used, which possibly causes code duplication.

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

Edit. After reading first two answers: I don't ask here how to prevent such linker error. Assuming that I cannot move specialization to .cpp file and leave it in .h file with static or inline, does this cause code duplication and bloating in optimized build, when these functions are added to every .cpp file where .h file is included, even if they are not used?


回答1:


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

Correct.

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

Yes, like any normal non-template function:

Either Define the function specializations as inline

or Declare (but do not define) the 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 better options than using static, because making the functions static has other side effects, such as giving the functions different addresses in each translation unit, and making local static variables different in every translation unit. That's a semantic change, not just a solution to the linker error.

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

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

Assuming that I cannot move specialization to .cpp file and leave it in .h file with static ...

I can't see any good reason why that would be necessary, but anyway ...

... or inline, does this cause code duplication and bloating in optimized build, when these functions are added to every .cpp file where .h file is included, even if they are not used?

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

Your question is misleading because it appears to be about templates (the title is very clearly about templates!) but whether unused inline/static functions cause code bloat is independent of whether the functions are templates or not.

If your question is simply "do unused inline and static functions affect object size?" the answer is no, for both normal functions and function templates.




回答2:


Such explicit specialisations should be moved to a .cpp file or made inline. The linker will find them there. If you define them in the header you will be getting "already defined" error messages just like you would get them for ordinary non-inline and non-static functions defined in a header included by multiple compilation units.



来源:https://stackoverflow.com/questions/25529893/explicit-specialization-of-function-templates-causes-linker-error

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!