Here's a very different patch. This gets rid of the __ptr_rel_ops and just puts the special handling for pointers directly in the std::less<_Tp*> etc. specializations. Then std::less uses std::less for some pointer type P*. I've also added a ton of ugly metaprogramming to detect the "if the call operator calls a built-in operator comparing pointers" condition. The idea is borrowed from Casey Carter and Eric Niebler's Ranges work, but basically it checks if operator<(T,U) or T.operator<(U) can be called, and if not the comparison must be using a built-in operator. If both T and U are convertible to pointers (specifically, to const volatile void* which is the most accepting of all pointers) then we assume we're using a built-in operator comparing pointers, and delegate to std::less, which ensures a total order. Tested powerpc64le-linux, committed to trunk. This fixes a regression, but I'm not sure about backporting it yet, I haven't even tried testing it on the branches.