Well, OK, it's a matter of degrees.
In your example small parts of an operation can be customized by a
derived class. This is the template pattern. The parts typically have
few constraints imposed on them. For example, the `doStuff` operation
can be a general way to handle failures, where the customizable parts
are, first, some arbitrary main operation to do, let's call that A, and
second, a part that handles failure of A, let's call that B, that is
constrained to either itself fail, or else have changed the state
sufficiently (e.g. by just waiting a little) to let A possibly succeed
if tried again, and C, a cap on the number of retries.
For comparison, in the Barton-Nackman trick, as used for relational
operators, a number of operations are defined in terms of a single
derived class operation. Or a very small number of such. The derived
class operation is tightly constrained, e.g., that it must implement a
strict ordering.
Conceptually, with the template pattern there is a single algorithm for
something, that has customization points so that you can /change/ it.
While with a mixin class, conceptually you don't change anything, it
just adds capabilities to your class, based on its it-will-have-that
anyway basic functionality and possibly functionality elsewhere.
But you're right that there's much overlapping.
It's like, `goto` can be used to implement a `while` loop or a `do`
loop, but then, a `while` can be implemented in terms of `do`, and vice
versa. They're just used for different things. With different conceptual
pictures and slightly different associated guarantees.
>> This relied on a subtle rule, called "friend name injection", that have
>> since been removed because the Barton-Nackman trick was its only use;
>> instead a friend function defined inline in a class is now found via
>> argument dependent lookup, so that the trick still works.
>
> I assume that "friend name injection" and ADL come into play
> because we're defining operators (where ADL is most useful),
> but, other than this syntactic issue, we're just working with
> otherwise regular member and/or friend functions. Or am I missing
> something important about the Barton-Nackman structure.?
It's having e.g.
friend
auto operator<( Derived const& a, Derived const& b )
-> bool
{ return compare( a, b ) < 0; }
directly in the CRTP base class.
It's not a member function, yet must be found and invoked when client
code has `a < b` with objects of the derived class.
So it's /like/ placing this definition at namespace scope, yet it's
inherited in, which you can't do for a real namespace scope function.
Cheers & hth., possibly others will chime in with better explanations!,
- Alf