multiple definition of template specialization when using different objects
The keyword inline
is more about telling the compiler that the symbol will be present in more than one object file without violating the One Definition Rule than about actual inlining, which the compiler can decide to do or not to do.
The problem you are seeing is that without the inline, the function will be compiled in all translation units that include the header, violating the ODR. Adding inline
there is the right way to go. Otherwise, you can forward declare the specialization and provide it in a single translation unit, as you would do with any other function.
You've explicitly instantiated a template in your header (void Hello<T>::print_hello(T var)
). This will create multiple definitions. You can solve it in two ways:
1) Make your instantiation inline.
2) Declare the instantiation in a header and then implement it in a cpp.
Here is some piece of C++11 standard related to this issue:
An explicit specialization of a function template is inline only if it is declared with the inline specifier or defined as deleted, and independently of whether its function template is inline. [ Example:
template void f(T) { /* ... / } template inline T g(T) { / ... */ }
template<> inline void f<>(int) { /* ... / } // OK: inline template<> int g<>(int) { / ... */ } // OK: not inline — end example ]
So if you make some explicit(aka full) specializations of templates in *.h
file, then you will still need inline
to help you get rid of the violation of ODR.
Intuitively, when you fully specialize something, it doesn't depend on a template parameter any more -- so unless you make the specialization inline, you need to put it in a .cpp file instead of a .h or you end up violating the one definition rule as David says. Note that when you partially specialize templates, the partial specializations do still depend on one or more template parameters, so they still go in a .h file.