C++ has been trying to get single-ownership semantics to work right for almost two decades. "auto_ptr" went through three standards revisions before the C++ standards committee finally gave up and dropped it. Now there's unique_ptr, where, after sprinkling on some move semantics, almost works, with fewer holes than auto_ptr.
Getting this right needs a borrow checker, like Rust's. Now that borrow checking has finally been figured out, there's a way out of this mess. Trying to do borrow checking via the type system just doesn't work out well.