Inlining Template Specialization

落爺英雄遲暮 提交于 2020-05-27 02:14:09

问题


If I have a header foo.h which I include all over my project, it seems to work fine when all it contains is:

template<typename T>
void foo(const T param) {
    cout << param << endl;
}

But I get one definition rule (ODR) errors when I add a specalization to foo.h:

template<>
void foo(const bool param) {
    cout << param << endl;
}

Obviously I can solve this by inline'ing the specialization. My question is, why do I need to? If the template doesn't violate ODR, why does a specialization?


回答1:


An explicit specialization is not implicitly inline. It must be explicitly made inline.

[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 ]

So you have to do it, because the standard says you have to do it.




回答2:


The reason why templates are exempt from ODR is simply that there is no other choice.

A template is not a "tangible end-product" from compiler's perspective. The implementation of templates must be carried around so that it can be expanded into compilable code when used. As a result, it must reside in a header file, and duplicate definitions from different compilation units are consequent and unavoidable. Since it is unavoidable, the standard makes a compromise to exempt them from ODR.

A function is an end-product that can be readily compiled into target code, so compilers hate to see potentially conflicting definitions, even if it is entirely possible to compare the codes and proceed if the codes are identical. However, the compilers decide they are way too lazy to do such extra check, and hence the standard banned multiple definitions.

Now, an explicit/full specialization of a template function is de facto a function, not a template - as all the missing pieces have been filled and there is no need to carry the definition of the specialized function around anymore. In contrast, a partial specialization is de facto a template, as its implementation still needs to be carried around during compilation. Therefore, partial template specializations enjoy the exempt inherited from templates, whereas explicit/full specializations don't.



来源:https://stackoverflow.com/questions/51987423/inlining-template-specialization

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