For good companies; there are _quite_ a few companies that underpay and not as many interesting job opportunities. Let's just say "at least 2x~2.5" and move on.
Also, even if you did not mention it, UK is a bit of a special case (English-speaking countries that has thus been attracting quite a lot of international talent (and companies) at least until recently), I wouldn't put it in the same bucket as EU countries.
There is a lot of everything and I got lowballed with 85 today (with three mandatory hebeas corpus days, while the rest of the team is in a different country lol).
I'm not sure where the UK part comes from zo? Nobody upthread mentioned it.
> The C++ inline keyword is treated similarly as well, with different metrics used of course.
You are thinking of C's inline/static inline.
C++'s "inline" semantics (which are implied for constexpr functions, in-class-defined methods, and static constexpr class attributes) allow for multiple "weak" copies of a function or variable to exist with external linkage. Rather than just an optimization hint it's much more of a "I don't want to put this in any specific TU" these days.
Even global mutable variables are a problem only because they lend to spaghetti code and messy state handling if you use them in multiple places. But you could just... make a global variable and then handle it like you would a variable init with malloc. No functional issue there.
A lot of it is about making metaprogramming a lot easier to write and to read.
No more enable_if kludges since if constexpr (and concepts for specific stuff); and using concepts allows to better communicate intent (e.g.: template<typename I> can become template<std::integral I> if you want the template to be used only with integer types, and so on)
Most of the complexity comes from the fact that C++ trivially supports consuming most C code, but with its own lifetime model on top, and that it also offers great flexibility.
Of course things become simpler when you ditch C source compat and can just declare "this variable will not be aliased by anyone else"
AFAIK C++'s constexpr and TMP is less limited than Rust's is.
True, but that's a fault of the implementation, which assumes POSIX is the only thing in town & makes questionable optimization choices, rather that of the language itself
The "language" is conventionally thought of as the sum of the effects given by the { compiler + runtime libraries }. The "language" often specifies features that are implemented exclusively in target libraries, for example. You're correct to say that they're not "language features" but the two domains share a single label like "C++20" / "C11" - so unless you're designing the toolchain it's not as significant a difference.
We're down to ~three compilers: gcc, clang, MSVC and three corresponding C++ libraries.
> I’ve lost track of how many times I’ve listened to Kate Gregory extol the virtues of const-ing all the things, but people still don’t systematically add it
Adding const to _function-local_ variables only really matters when you "leak" a pointer or ref, whether mutable or const, to a function or variable the compiler can't optimize away:
std::size_t sz = 4096;
const std::size_t &szRef = sz;
some_opaque_func(szRef);
if (sz != 4096) std::abort(); // cannot be optimized away unless sz is const
as there is no way to know if something obtains a mutable ref to sz down the line.
In other cases like RVO, adding const is actually detrimental as it prevents the move-constructor from being selected (likewise with the move assignment operator).
Rust _needs_ to have const by default due to its aliasing model ("only one mutable ref per object") and you can't have cheap bound checks without this. But that, too, is a tradeoff (some classes of programs are hard to code in Rust)
Pretty sure the std::abort() can't be optimized away if sz is mutable since it's legal for some_opaque_func() to cast away szRef's const and modify sz via that. sz itself needs to be const for the if statement to be removable as dead code.
reply