|
Hi!
We have some confusion about rule A3-1-5:
A function definition shall only be placed in a class definition if (1) the
function is intended to be inlined (2) it is a member function template (3)
it is a member function of a class template.
As non-native English speakers, the "shall only" part of the sentence is not exactly clear to us. We can think of 2 interpretations:
1) A function definition may be placed in the class definition only if it fulfills any of the 3 points.
2) If a function definition fulfills any of the 3 points, then it shall (must) be placed in the class definition.
The rationale and examples seem to implement interpretation 2), but we believe interpretation 1) makes more sense.
Consider the following use case of a template class that doesn't need to be generic, i.e. it's only meant to be used for a handful of types. This pattern is widely used for static dependency injection:
Code: // foo.h
template <typename Impl>
class Foo
{
public:
// Long, complicated function with many dependencies:
// implement in foo.cpp to keep header clean, speed up
// compilation time, etc, etc.
void run();
private:
Impl impl_{};
};
// foo.cpp
#include "foo.h"
template <typename Impl>
void Foo<Impl>::run()
{
// Implementation...
}
// Explicit instantiation for the only 2 possible cases
template class Foo<RealImpl>;
template class Foo<MockImpl>;
As you can see, this is a perfectly valid use case where a template class can be implemented in a .cpp file, with all the advantages that come with this.
Now, A3-1-5, the way it's described in the rationale and examples, would forbid this use case, and force us to move hundreds of lines of implementation of perfectly valid code from the source file to the header file. This in turn clutters an otherwise clean header, greatly increases compilation time, etc, which is pretty bad. That's why best practices always recommend to put the implementation in the source file as much as possible.
The rationale for the rule is rather weak, in our opinion. "template syntax elements (e.g. parameter list), which makes code less difficult to read and maintain." Readability is hurt much more if we clutter the header file with implementation details. Besides, it's not "difficult to maintain", as the compiler will easily catch any mismatch between header and source (just like it would for a non-template class).
Therefore here's my question - is the rationale and examples for A3-1-5 what they intended to be, or was there some confusion in the interpretation of the "shall only" part of the rule, and therefore it should be corrected? Should we interpret the rule as 1) or 2) above?
Thanks a lot!
|