Why do templates specialisations need to be inlined?

蹲街弑〆低调 提交于 2020-01-21 01:34:52

问题


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

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