I'm nowhere near smart enough to do C++ well.
This is a bit of an illusion. If it would benefit you to know C++ better, I'd encourage you to not give up easily.
First, it's an illusion because when you read some template code by an expert like Andrei Alexandrescu, it's easy to imagine that this code flowed out for him as easily as writing Python is for you. But writing that kind of code is a slow thoughtful process even for experts, and even they get it wrong sometimes.
Second, it's an illusion because you're comparing your limited experience with C++ programming to people who have been doing it for decades. C++ just takes longer to learn that the languages you mentioned. Even when you feel you're starting to get the hang of it, a few years later you'll look back and realize you're still learning a lot. It isn't a matter of intelligence so much as persistence and continuing to expand your knowledge rather than settling down on some habits that work well enough but don't really take advantage of the full language.
And finally it's an illusion because other languages that have the expressive power of C++ aren't really simpler except in syntax. Consider for example a generic version of the useless function mul(a,b) which returns a times b, in C++, D, and Standard ML:
template<typename A, typename B>
auto mul(const A& a, const B& b) -> decltype(a*b)
return a * b;
auto mul(A, B)(A a, B b)
return a * b;
It appears that SML is simpler than D which is simpler that C++, but that's really just syntax. All of these are strongly typed, compile-time type checked, and work for arbitrary types. For example if a is a float and b is a vector of integers, then a*b is a vector of floats, which is a different type than a or b. Another example is if a is a 2x3 matrix and b is a 3x2 matrix, the return value is a 2x2 matrix. Generic programming requires you to think abstractly about operations where you don't know what the types are going to be. mul(a,b) is trivial, but if you imagine a more complex algorithm, you can see it's going to require careful thinking. It's just harder than working with concrete types, regardless of the language. Dealing with the syntax is just an annoyance.
The reward is that you get very powerful code that can be reused in many more situations without compromising type safety or performance.
I used generic programming as an example, but the same kind of arguments apply for object oriented, procedural or even functional programming. The real beauty of C++ (and D) is that you can combine these styles of programming according to what's appropriate for the task at hand. But you shouldn't expect that to be as easy as learning OOP in Java or procedural programming in C.