Lets say you have simple templa开发者_Go百科te function (not class member for the sake of simplicity) with type specific specialization in the same .h file...
template <class TYPE>
void some_function(TYPE& val)
{
// some generic implementation
}
template <>
inline void some_function<int>(int& val)
{
// some int specific implementation
}
Unless you explicitly direct you compiler to inline
the specialization (inline
keyword) you will get linking error if .h file is included more than once (at least I do in Visual C++ 2008).
inline
is just a suggestion to the compiler, which it can ignore. In this particular case is compiler allowed to ignore this suggestion and let linker to fail?If you don't use inline
, then the same function gets compiled with extern
linkage into multiple .obj
files, which causes the linker to throw a duplicate symbol error.
This is independent of whether the compiler actually compiles your function inline, since it could treat it the same as a static
function and make each implementation private to each compilation unit. However, you can't use static
for this purpose since it means something else on member functions, so inline
is your only choice.
You are misunderstanding the meaning of the often-mentioned "ignore inline" possibility.
No compiler is ever allowed to ignore the inline
specifier used in function declaration and the consequences this specifier has with respect to One Definition Rule (ODR).
When someone says that compiler are allowed to "ignore inline", it only means that compilers are not required to actually inline the calls to the function in question. To "ignore inline" means to generate an ordinary (non-inlined) function call to an inline function.
In any case, even if the compiler decided to always generate ordinary calls to an inline function (i.e. to always "ignore inline"), it is still required to treat the function as inline for the purposes of ODR. How the compiler is going to do it is the problem of the compiler. You are not supposed to worry about it.
In your original example you should not not get any linker errors.
This is defined by the standard and the compiler is totally compliant in this regard, from the looks of it. The linkage is all you are after. Implicit template instantiations have 'special' linkage, as inline functions do. There is also static (keyword), which has been deprecated in favor of anonymous namespaces:
namespace {
…declarations…
}
So yes, this specialization (in your example) has the same linkage as:
void some_other_function(int& val) {
// some int specific implementation
}
In fact, the compiler may mumble about inlining the specialization, in your example, saying they do not match. So it really is a best practice to label them both inline (or otherwise).
I believe you can explicitly declare the method as extern and then put the specialization into a .cpp. I've tried something similar in a past life with GCC, but I don't recall the exact details of how it worked. MSDN Magazine has an article on this that might help.
What you're actually seeing is the One Definition Rule (ODR) has a special case for inline functions, in that each TU may have a definition. If the function, such as your explicit int specialization, is not inline, then you will get multiple definition errors at link time. Such inline functions still have external linkage. Function templates are templates and so follow different rules. Instantiations/specializations of a function template are functions.
Using inline, as for any function, is just a hint, but you might want to apply it if the function is short (as for any function) or if you just want to keep it in the header. Here's an example without inline:
Header file:
template<class TYPE>
void some_function(TYPE& val) {
// some generic implementation
}
template<>
void some_function<int>(int& val);
Implementation (.cpp) file:
template<>
void some_function<int>(int& val) {
// some int specific implementation
}
精彩评论