On GCC 10's libstdc++, instantiating std::pointer_traits<P> for
non-pointer-like types triggers a static_assert that cannot be caught
by SFINAE or requires clauses. Fix by checking for P::element_type or
p.operator->() instead of std::pointer_traits<P>::to_address(p), and
using if constexpr to dispatch appropriately in the function body.