https://gcc.gnu.org/bugzilla/show_bug.cgi?id=96416
--- Comment #11 from Glen Joseph Fernandes <glenjofe at gmail dot com> --- > if it can never be used. You're misunderstanding. to_address(p) requires that pointer_traits<P> is valid. It just doesn't need to have a to_address member function. Example 1. You have a pointer-like type Ptr1. You haven't specialized pointer_traits<Ptr1>, but pointer_traits<Ptr1> is valid. Here it will call to_address(p1.operator->()). Example 2. You have a pointer-like type Ptr2. You have specialized pointer_traits<Ptr2> with a to_address function. Here it will call pointer_traits<Ptr2>::to_address(p2). to_address() was intended for used with pointers and pointer-like types (and pointer_traits<Ptr> was always required to be valid). It was intended for use with allocator pointers, and the original standard library implementations had a return type of: typename pointer_traits<Ptr>::element_type* If (for contiguous iterators, which came later) you want pointer_traits<X> to be valid even when X does not have element_type, that is a design change to pointer_traits.