There is no added value to static
member functions, as you correctly identified. Worse, when used for implementation details this introduce extra dependencies (in term of compilation).
The only use that could not be emulated with an anonymous free-function, is the protected
access, that is, a derived class accessing a parent static function. However, this is never required: you can just make it a regular member function instead (I assume you don't have global state, otherwise the static/friend distinction is not of immediate concern).
The use of static
functions in template meta-programming has been evoked... however it is very similar to the inner types issue: it makes it difficult to provide a default version. On the other hand, a suitably defined free function (which takes the type as a pointer), can propose a template version:
struct some_traits
{
static void doStuff();
};
// versus
struct some_traits {};
void doStuff(some_traits*);
// and the default: void doStuff(...);
And of course, there is always the question of why this should be a static function, when a member function would provide more flexibility to the user. To this effect I would cite the move the Standard Committee made with the Allocator
concept: stateful allocators are now authorized, which gives us the opportunity of packing the nodes of a given map
in a same page rather than spreading them all over the heap.
Finally, there is the interface issue. However it's been a long time already since Sutter advocated that a class and the free functions defined in the same header both constituted the public interface of this class => that is what ADL is for! So it is more something to comfort ancient OO-programmers than a "good practice".
Really, I don't see any benefit from using static
member functions. I would like people would think the contrary to propose real cases.