Using Swappable correctly is not an exceptions to any rule.
No one is suggesting that using std::swap; should be placed at global scope in a header file.
I suspect seeplus' "exception proves the rule" commentary was related to my string and string_view literals missive. :)
Personally I would never have using std::swap; in any of my code.
There's bein' lazy, and then there's being stupidly lazy. Having that form of a using declaration is IMO the latter.
About the string and string_view literals....
If'n I read the write-up at cppreference correctly having a user declaration to access those operators is practically a requirement. Maybe it is, maybe it ain't. The operators are buried deep in layered namespaces. Having a using declaration ain't saving just a couple of keystrokes when using the operators.
I do know a using declaration, in as narrow a scope as possible, is very much preferred vs. the using directive. Global or in a header is especially not a good idea.
ADL works by having all the necessary stuff in scope. The trick is to simply keep the scope appropriately small.
For example:
1 2 3 4 5 6 7
template <typename Container>
void foo( const Container & container )
{
using std::begin;
using std::end;
quux( begin(container), end(container) );
}
If you don’t pull those two into the current scope, they won’t be considered when the compiler is trying to figure out which begin/end functions to use, and calling a generic foo( my_string ) or foo( my_array ) will fail.
We (typically safely) assume that whatever non-std type we are using is already in-scope, and only need to pull in the std stuff for everything else.
The same is true for std::swap, and JLBorges already pointed that out.
It isn’t lazy. It is correct when writing generic code.