@Barry's suggestion of `using` seems a reasonable solution to me, but in the end doesn't really save much given how simple a (non-template) operator<< for S would be.
I like the idea of a base class used just to guide ADL to the right answer. I'll have to see if that is feasible in our real codebase.
The problem with putting the template in global namespace (or in N) is that works.... but only sometimes. Because this is relying on normal, non-ADL lookup, it is subject to shadowing. So if _any_ other operator<< is visible in N::N1 namespace the one in N (or global) namespace is hidden. This is very fragile and working code can be broken by completely unrelated changes, and the failure can be very context dependent (i.e. works for most usages but fails if some unrelated type N::N1::C, which happens to have an operator<< , is visible.)
As to the original question of adding to std:: namespace, it might be argued that this case might be counted under this clause (from cppreference)
It is allowed to add template specializations for any standard library function template to the namespace std only if the declaration depends on at least one program-defined type and the specialization satisfies all requirements for the original template, except where such specializations are prohibited.
as std::operator<<(std::basic_ostream<C, Trait>&, T)
is already a template (for at least some types, in at least some implementations) and we are adding a partial specialisation of that.