let value = match attempt_something() {
Ok(value) => value,
Err(error) => return SomeErr::Kind(error),
}That way you only need to type
let value = do_something().map_err(SomeErr::Kind)?;
It was called for by the community because error checking is something that can happen multiple times within the same function. Simply passing the error up the chain and handling all your errors in a central location is highly convenient, especially when matching requires that you handle all cases.
Additionally, in no way is C++ more efficient at error handling that Rust. Rust is able to perform this with zero allocation costs.