C++ has approximately eighteen different partially-overlapping categories of variable initialization, many of which are legacy-but-still-used! [0] And some of those categories have changed their boundaries every language version since C++11 (based on the definition of "aggregate").
C++ has three to five partially-overlapping kinds of type inference all in active use (auto, decltype(id), decltype((expr)), decltype(auto), template argument deduction)! This is interleaved with name lookup and overload resolution (below), so if some subexpression isn't compiling how you expect, you have a vast space of language features potentially to blame.
C++ has so many kinds of name lookup and namespacing that I'm not even sure how to count them. There's unqualified lookup, argument-dependent lookup, qualified lookup, class member access, etc. Sometimes you can't refer to things defined later (outside a class) and sometimes you can (inside a class). There is even undefined behavior if you mess up namespacing! (Undiagnosed ODR violations are every experienced C++ programmer's nightmare.)
C++ has ad-hoc overload resolution based on un-scoped identifiers, which even crosses namespace boundaries using one of the above name lookup modes. It has two kinds of user-defined implicit conversions ("explicit" and implicit) that also affect this selection process, on top of the zoo of "type promotions" inherited from C.
C++ classes have five to six kinds of "special member functions," some of which may be defined automatically by the compiler, each with its own rules for when and how, based on what else is defined in the class. These also contribute to overload resolution, of course.
[0]: https://blog.tartanllama.xyz/initialization-is-bonkers/
Rust has a complexity of its own, but it's quite different in scale and quality. There is exactly one way to initialize a variable, exactly one kind of type inference, only two ways for names to be resolved (directly or via an imported trait). Overloading, implicit conversions (of which there is only one kind, Deref), and the replacement for "special member functions" (Copy, Clone, Drop) are all based on exactly one mechanism (again, traits).
The article has a pretty accurate description of how people experience Rust's remaining C++-like complexity, IMO: "I don't remember the order in which methods are resolved during autoderefencing, or how module visibility works, or how the type system determines if one impl might overlap another or be an orphan."
But one important aspect it leaves out (not being a C++ article) is that if you mess up any of these, you just get a compiler error- and Rust is well-known for having extremely helpful error messages. In C++ you may get a compiler error (known for being extremely unhelpful) or you may get undefined behavior.
Zig is certainly a smaller language than either C++ or Rust, but that comes at a cost. I would much rather hear discussion of those actual trade-offs than yet another "Rust is just as complicated as C++" non-claim.