Why do compilers complain about a non-template class defined in multiple .cpp files but are fine with a template class the definition of which is duplicated across various .cpp files (via inclusion of the .inl file of the class), even if the class is explicitly instantiated in even multiple .cpp files?
3 回答
The non-template case is because in that scenario your program violates the one definition rule so the linker (not compiler) will complain about multiple definitions.
For templates on the other hand, the language specifies that this must work and the linker sorts out what to do. I'm not 100% sure if an explicit template instantiation should be treated the same as a non-template function though.
Do all compilers complain, always? I've never seen one which did, and the standard doesn't allow it: you're allowed to define a class or a template once in each translation unit, as long as all of the definitions are identical. In fact, you're required to define the class in every translation unit which uses it in a way that requires it to be a complete type. C++ does not have any mechanism for exporting class definitions to other translation units.
Are you sure you're not confusing classes with functions. You're not allowed to define a function more than once, unless it is inline. You still have to define a function template in each translation unit which uses it, and the same rules apply for function templates as for classes and class templates.
Note that if you violate these rules, by defining the function in more than one translation unit, or by the definitions of the classes or templates not being tokenwise identical (after preprocessing, and including name binding), then you have undefined behavior. The compiler (actually the linker) may complain about it, but it's not required: most complain about multiple definitions of a function, but I don't know of any which complain when the class or template definitions differ between translation units.
Template functions are inline, and inline functions are allowed to be defined in multiple compilation units as long as each definition is identical.