While puzzling with some facts on class design, specifically whether the functions should be members or not, I looked into Effective c++ and found Item 23, namely, Prefer no
The motivation is simple: maintain a consistent syntax. As the class
evolves or is used, various non-member convenience functions will
appear; you don't want to modify the class interface to add something
like toUpper
to a string class, for example. (In the case of
std::string
, of course, you can't.) Scott's worry is that when this
happens, you end up with inconsistent syntax:
s.insert( "abc" );
toUpper( s );
By only using free functions, declaring them friend as needed, all functions have the same syntax. The alternative would be to modify the class definition each time you add a convenience function.
I'm not entirely convinced. If a class is well designed, it has a basic functionality, it's clear to the user which functions are part of that basic functionality, and which are additional convenience functions (if any such exist). Globally, string is sort of a special case, because it is designed to be used to solve many different problems; I can't imagine this being the case for many classes.