Can you be more specific and/or support the argument that the tools for C++ are behind what's available for Java?
Visual Studio has had Intellisense since forever, clang-format can enforce style standards, static analyzers these days are amazing, the address sanitizer and valgrind find memory problems easily, etc.
> Can you be more specific and/or support the argument that the tools for C++ are behind what's available for Java?
The most obvious example to me is in Eclipse, you can right-click on a field in a Java class and choose to Rename it. It will then correctly update that field's name across the entire codebase. AFAIK this is impossible in C & C++ because they are such complicated languages to parse. Macros alone make this feature effectively impossible.
Java had it first (by at least 10 years), but C++ IDEs do the same. Clang not being designed to make it impossible to access the AST has made this feasible for most IDEs. There are still cases where it cannot be done (macros), but in many cases it can be done now.
Jetbrains makes excellent refactoring tools for multiple languages so I usually use their tools as my gauge of how well a language lends itself to refactoring.
As a daily user of Resharper in both C# and C++, I really notice how much poorer they work in C++. Renaming operations, as you mentioned, do work in C++ sometimes, but not others. Generally if it is a variable or parameter that's used locally I can rename it instantly with no problem. If it's a variable exposed in the class header, then it will tend to sit there churning for enough time before I decide that I should probably cancel the operation.
Likewise, simply using a "Find References" or "Find Usages" in C++ usually works, but at times it gives odd suggestions of things that are clearly not usages of the thing I'm searching, but something else with the same name that it just is not smart enough to understand is not a real usage. (possibly due to the difficulty of parsing templates or macros)
"Extract Method" is one of my favorite C# refactorings. Resharper C++ also has this operation but it is a bit of a gong show, and generates results that usually have to be tidied up considerably afterwards.
You can't reliably refactor members in a template because T might be any class. Example: template <typename T> void foo(T bar) { bar.buzz(); }
Try renaming buzz in this context, you really don't know how many other classes that need the same rename. In Java and C# you know because of generic constraints and IDEs can leverage this information. Concepts in c++20 should hopefully solve this.
A C++ parser needs a semantic analyzer. The grammar is context sensitive. Eyeball a full year for an engineer to get one that's actually standards compliant. I've written a Java parser in two weeks in grad school while taking classes. You can easily use a parser generator (like ANTLR) because you have a context-free grammar.
Java generics are just syntactic sugar for Object, so not a problem at all since you can't do anything with them.
Java overloading is simple since all functions are in the same file (so doesn't change overload behavior depending on which files are imported) and Java lacks the user type casts C++ has, so just pick the signature fitting all provided values (with numeric casts) or throw.
> Java generics are just syntactic sugar for Object,
Only if you do not have a concrete boundary in the generic declaration, T extends Foo can result in a function definition that takes a Foo instead of an Object.
> Java overloading is simple since all functions are in the same file (so doesn't change overload behavior depending on which files are imported)
import static java.lang.Math.*; for programmers too lazy to write Math.sin instead of sin.
ICEs [1] used to be very common from all front ends especially with malformed template code, but now a day I think most compilers don't report an ICE to the user as long as they managed to issue at least one diagnostic.
It is still not uncommon to se ICEs on some extreme template constructs.
[1] Internal Compiler Error, i.e. the compiler segfaulted or hit an internal assertion.
They're slowly becoming available via clang now, which is nice.