问题
I am referring to this answer:
https://stackoverflow.com/a/4447057/930315
I ran into a similar issue as the OP of the cited question, having a function
template<typename T>
void func(T& val);
and its specialization
template<>
void func<mytype>(mytype& val);
resulted in a duplicate symbols linker error (the methods are implemented in a '.tpp' file that is included at the end of my header).
adding inline
to the specialised function resolved the issue. Why?
回答1:
According to clause 3.2:4 in the c++ standard
Every program shall contain exactly one definition of every non-inline function or variable that is odr-used in that program; no diagnostic required. The definition can appear explicitly in the program, it can be found in the standard or a user-defined library, or (when appropriate) it is implicitly defined (see 12.1, 12.4 and 12.8). An inline function shall be defined in every translation unit in which it is odr-used.
This explains why there is a link-time error when the specialized function is not declared inline. The program will contain multiple definitions of the specialized function, one from each module including the .tpp-file and this breaks the condition from the standard. When declaring the specialized function inline
it will make the function satisfy the second part of the same clause, i.e. that an inline function must be defined in each module using the function.
When the parameterized function is not specialized it is covered by clause 3.2:6:
There can be more than one definition of a class type (Clause 9), enumeration type (7.2), inline function with external linkage (7.1.2), class template (Clause 14), non-static function template (14.5.6), static data member of a class template (14.5.1.3), member function of a class template (14.5.1.1), or template specialization for which some template parameters are not specified (14.7, 14.5.5) in a program provided that each definition appears in a different translation unit
This clause states that it is OK for multiple definitions of the same template function as long as at least one of the template parameters is not specified in the code. This is to allow the decision on whether the parameterized function should be instantiated in a module to be made on local information only.
回答2:
Well, if you want the standard quote on this, that'd be over at [temp.expl.spec]/12
An explicit specialization of a function or variable template is inline only if it is declared with the inline specifier or defined as deleted, and independently of whether its function or variable template is inline. [ Example:
template<class T> void f(T) { /* ... */ } template<class T> inline T g(T) { /* ... */ } template<> inline void f<>(int) { /* ... */ } // OK: inline template<> int g<>(int) { /* ... */ } // OK: not inline
— end example ]
That's why you have to do it. It's independent because I believe doing otherwise would be needlessly restrictive, as Yola demonstrated.
回答3:
This will work without inline:
file1.h
template<typename T> void func(T& val);
template<> void func<mytype>(mytype& val);
file1.cpp
template<> void func<int>(int& ) {}
But if you define template specialization in header file, than you may violate ODR
来源:https://stackoverflow.com/questions/48402633/why-do-templates-specialisations-need-to-be-inlined