I agree on (1). Typedef obscures more than it helps.
On (2), I think the solution is intrusiveness. intrusive data structures and intrusive_ptr should be used more in C++.
The dislike for intrusiveness is rooted on equating classes with responsibilities. A single responsibility is often spread over several classes, because the classes form a useful cluster. A clear case is items of a collection. If an object already knows it's an item in a collection, there's really no harm in using intrusive lists.
Intrusiveness also isn't so good when you want the class logic to be independent of the memory management scheme in use. We experimented with language support for intrusive data structures in Rust (`@class` for an intrusive `shared_ptr`) and it turned out to be a lot of trouble, so we removed it.
On (2), I think the solution is intrusiveness. intrusive data structures and intrusive_ptr should be used more in C++.
The dislike for intrusiveness is rooted on equating classes with responsibilities. A single responsibility is often spread over several classes, because the classes form a useful cluster. A clear case is items of a collection. If an object already knows it's an item in a collection, there's really no harm in using intrusive lists.