Works perfectly fine for me on FF with uBO and all scripts blocked. Apparently that "Sorry, ..." comes from a cookie popup which I don't even see so seems like you need stronger blocking in your browser.
I have all scripts blocked with NoScript and saw it. I enabled redhat.com and the site rendered but took obscene liberties with polluting the back history after scrolling down.
There is a tag ###seckit-noscript-tag which shows up with uBlock Origin under 'Cosmetic Filters' which lets you view it without enabling JS (disabling NoScript on Firefox).
It's nice to see how GCC developers have worked hard in recent years to keep their compiler up to the most current standard. It's sad the same can't be said about Clang which, despite the fact LLVM has basically EVERYONE behind, still struggles to implement the entirety of C++20 after more than 2 years. And this is without taking libcxx into account, which has been also struggling despite the fact is way newer and cleaner than libstdc++.
It's basically as if Google and Apple don't really give a damn about keeping up with C++ standards, so they always get pushed on the back burner.
I don't see how the license is relevant here. It's not like companies have already implemented full C++20 support in their local forks and just haven't bothered upstreaming it.
But yes, a lot of LLVM users don't care about C++ standard compliance at all, for example because they don't use C++.
C++20 is coming into a world with much more competition than C++11 did (the last comparably sized standard). When C++11 came out Rust, Go, Zig, Swift were all either in their infancy or didn’t exist yet. There was a huge desire for C++ to improve and improve fast given its centrality.
That world is not today’s world. Projects that would have been written in C++ in the past are often written in a different language now. This leaves C++ being useful mostly for legacy codebases, of which adopting new standards quickly is not so important.
I think a large reason of why Clang lags behind in C++ standards is that Google and Apple don't really use modern C++ at all. Google has strict guidelines that prevent people to use half of the language (look at exceptions, for instance, without which most of the STL is crippled) and they use Abseil anyway, so they don't really care about the STL in the first place.
Apple on the other hand mostly uses C++ in very restricted scopes such as DeviceKit which are very limited and can't safely use the entire language anyway. Xcode-shipped Clang and libcxx are often pretty old, too. They don't really need C++ that much above what C++03 already had, so it's clearly an afterthought for them.
That alone doesn't explain why clang conformance was very good till c++17 and then suddenly fell behind. The major clang contributors decided to focus their attention elsewhere,
One guess is because they didn't get what they wanted within the committee.
Google basically withdraw from clang after they lost the ABI vote, and Intel is now taking care of what used to be mostly Google stuff.
If I remember correctly some discussions on /r/cpp.
As for Apple, OP is right, Metal Shaders are based on C++14 dialect, IOKit/DriverKit use an Embedded C++ dialect, and for everything else there is Objective-C/Swift, and they only need enough C++ to use LLVM to develop them.
I would not be surprised if google (or others in favor of breaking the ABI for the c++ standard library) would refocus on their alternate non-std std-replacement-ish library implementations (like abseil) instead given the lack of willingness to fix things in std proper from the committee.
Yeah, I've seen both of those before, but was unsure if it was just the position of a single Google employee or the position of google as a whole, as you made it sound like Google the company had actually taken such a stand
The permanent-ABI compatibility decision was effectively the death-knell for C++. Can't improve the standard library performance, making it effectively useless for the real world. Can't correct mistakes - the language and library warts grow and grow as the years pass by, making it impossible for beginners to pick up and learn the language.
Frankly, Google should fork C++ and create a new language without the warts and a new standard library.
Golang isn't really a C++ replacement, the performance metrics just aren't comparable. It's more of a Python replacement, for those applications where it would be just too slow, forcing you to write C or C++ because that's still the #1 way to accelerate your Python. Sure there are compilers such as Cython or Nuitka, but they just do not suffice when you _really_ need to speed up your code.
In C++‘s heyday there were things such as OKWS[0] web application server. Yes externally C++ was no so popular in such situations, but at Google they had/have many such C++ services and that was the motivation behind Go - a safe language to build mostly-IO-bound-but-a-little-bit-CPU-bound services.
Another example of this shift would be that Bitcoin’s reference impl (2009) is written in C++, whereas Ethereum’s reference impl (2015) is written in Go.
The golang genesis story is that pike, thompson and company were so dissatisfied after a ISO C++ meeting that they just decided to make a C++ replacement that checked all the boxes they wanted. They got somethings wrong. They got somethings right. But, overall it was their NIH reaction to what would become "Modern C++".
I meant a language by removing all the warts, not removing all the features. :)
Seriously, if Go offered manual/arena memory management and real generic programming - stuff like template template parameters, STL algorithms, auto-vectorization, etc - it could effectively replace C++.
Now, one of the things which you may have noticed really annoys C++ proponents here on HN is when people say "What Rust does..." and well, maybe Vittorio should not have done that in his talk. But the reason he's saying it is that although Rust has very few new ideas it popularises lots of existing ideas from PL theory that were not seen in the kind of languages C++ developers had experience with before.
A few slides in, Vittorio explains that he's not offering language fragmentation or dialects, an ABI break, or yet more stuff every programmer needs to learn. Nevertheless, criticisms of Epochs generally say that this is language fragmentation, it introduces dialects, it's an ABI break, and every programmer will have to learn all this extra stuff so it's hopeless...
Chromium finally switched to C++17 this year. The switch to C++20 will happen much sooner given that PNaCL support will be finally removed this summer.
Apple’s public/external-facing uses of C++ are restricted and odd (MSL, IOKit), but internally it seems pretty common in the OSes. Dyld, font rendering, and lower-level event handling (the remains of Carbon/HIToolbox) are all things I’ve seen in stack traces.
C++ is great to have as much control over memory and performance as possible, while still providing more convenience than C. The C++ Standard Library and exceptions don't improve this control generally.
Possibly an unpopular opinion, but personally I wish the C++ Standard Library was kept separate from the C++ language and have the C++ committee focus on the language features instead.
> Possibly an unpopular opinion, but personally I wish the C++ Standard Library was kept separate from the C++ language and have the C++ committee focus on the language features instead.
Java could never fill all of the spaces that C++ is used for because of the JVM and garbage collection. Rust certainly could, and should, in my opinion as a long time C++ developer.
> Rust certainly could, and should, in my opinion as a long time C++ developer.
I'm not a Rust dev, but I am curious how things like epoll would work in Rust. In C (or C++) I place a pointer to a structure in the epoll `event.data.ptr` field. When an event is returned by epoll_wait() all the caller has to do is run a function on that instance in `event.data.ptr`.
It seems to me, that even with `unsafe`, you're not going to be able to do this in Rust unless all the code is unsafe. You cannot transfer ownership of the instance to `event.data.ptr`, can you mark the pointer or event structure itself as `unsafe`?
> you're not going to be able to do this in Rust unless all the code is unsafe.
Why wouldn't std::mem::transmute (plus a little bit of hand-managed lifetime emulation) work here? It is unsafe, but doesn't require the unsafe modifier to be present on code beyond where the transmute happens. Unless by "all the code is unsafe" you mean related code is conceptually at risk of unsafety due to bugs caused by erroneous reinterpret-casts, then I think transmute should work here.
I don't see why that would require making all code unsafe? You might want to take a look at mio's source code [1], which uses epoll on Linux [2], and which encapsulates epoll in a safe way.
After looking at the examples, it looks to me that it uses a hashmap (with a generated token to identify the connection structure).
It gets around putting a ptr into the event structure (that epoll will then return) by putting a tokenID into it instead (that epoll returns), that the connection_handler function will then use to retrieve the connection instance that it needs to work with.
IOW, in `C` I'd create an instance of a `struct connection_t` and `epoll_wait()` returns the pointer to the instance.
This way, it appears that an ID is placed into the event structure and the { ID : corresponding instance } tuple is stored in a hashmap. `epoll_wait()` returns the ID, the caller uses that ID to get an instance to work with.
I think you’re blissfully unaware of just how many developers are still being trained in C/C++ this day. I agree with you that in the long run, Rust has everything going for it to replace C++, but these types of things happen in a span of several decades, not years.
I think Rust has the potential to coexist with C++. As for replacement - here is my shallow outlook (I only care about how new tech affects my own business).
The safety offered by Rust is not a thing to ignore. However modern C++ and the tooling has made enough progress in the area. It is extremely rare for me to allocate explicitly and in the couple cases where I do I always write deallocator first. It is ingrained in my nature along with some other related habits. Invalid memory access is also less likely with modern constructs. Along with memory sanitizers and practical experience with my own products I feel that Rust memory safety at this point does not offer much from my practical point of view.
I value very much time spent on compiling / building. From few experiments I made Rust is not any faster in this department. Rather the opposite.
As for C++ being a monster impossible to comprehend in its entirety. Agree and do not give a flying fuck. I am not there to explore language to its utmost depths. It is just a tool for me and nothing more. I do not get hung up on tools. As long as the tool lets me do my job with the reasonable ease (and subset of modern C++ definitely does) the rest does not matter. I do not feel inferior for not willing to spend the rest of my life trying to become Alexandrescu.
I write C++ for a living and I admit I do like to push it to its limits (SFINAE, constexpr/type traits shenanigans, the more the merrier), but it must be acknowledged that it tends to become too much akin to magic the more you push the envelope. Stuff like having 10 kinds of initialization and name resolution being incredibly complex and convoluted is a bit more confusing than what should be considered acceptable in a programming language.
Still I love the utter madness that there's behind C++, and the fact you can basically do everything you set yourself to, no matter how crazy and weird it is, as long as you accept to put up with the madness. You can emulate a good 90% of what Rust does with traits if you really want to.
>"I write C++ for a living and I admit I do like to push it to its limits (SFINAE, constexpr/type traits shenanigans, the more the merrier),"
I suspect maybe because you love programming as a process. I write C++ (other languages as well) for living but I am my own company, so my primary concern is to deliver more while spending less. The language on it's own means zilch to me as long as it adequate.
Well, by pushing C++ you can enforce a lot of constraints at compile time, just like you do with Rust. For instance, by extensively using concepts or SFINAE (enable_if and friends) you can make type safe code that works well and (almost) never breaks. I rarely if ever need to fix runtime issues with my C++ (or Rust), because it almost always works at the first attempt. That's due to all the "fighting against the compiler" you need to do beforehand in order to get the code to compile in the first place, but it's generally worth the effort IMHO.
I/my company personally did not ever encounter this particular issue so not a problem in my world. I understand it is still valid concern but I'd let the actual victims worry about it.
You sound like you work in a wonderful environment.
"where I do I always write deallocator first" that sounds like good practise.
But software development is driven by marketers. Having the time to properly add in the features required for safety is important.
From a marketing perspective it is a waste of money. When a change needs to be made, some feature that once lived under the hood and needs to be "surfaced", using some pointer into a structure in an unsafe manner will take five minutes, properly assembling the structures, rearranging the code etcetera takes two days - those days come off the profit of the company (from the marketing perspective)
As a computer programmer it is fabulous to have the resources to do it safely. It is not the conditions that a lot of us (most of us?) work in.
User visible features. All that matters. Memory safety? What is that!
>"You sound like you work in a wonderful environment."
For the last 20+ years I sit in the basement of my house where I design and build my products. Some for my company. Some for clients. Every once in a while I would get out and meet with perspective clients / subcontractors or for some meeting with existing ones. But it gets increasingly more rare and everything is done using Zoom/Skype/Remote Deployments/Couriers. The only reason I get out is mostly for fun - meeting friends, cycling, swimming etc.
> From few experiments I made Rust is not any faster in this department. Rather the opposite.
Rust uses more generics in its idiomatic code than C++. If you're careful to split out your generic type impls to avoid excess code monomorphization, compile times can be manageable. Macro use brings similar concerns, but it's probably rarer unless you're relying on popular crates that need it such as serde.
> C++20 is coming into a world with much more competition
I question whether those are actually competing in this same realm, for large organizations. Language adopotion is not just about the language, but also tooling, libraries, standard, etc which organizations have built up and rely on.
For example, at Apple C++ is used more internally than is exposed in public APIS. (I can't imagine the swift compilers performance scaling up to large code bases at this point.)
Can you speculate on other reasons, besides competition for the slower rate of adoption? Is it not as helpful as previous standards? Is it more difficult to implement?
> (I can't imagine the swift compilers performance scaling up to large code bases at this point.)
It struggles on medium sized code bases.
And Xcode becomes flaky too, on medium code bases.
Works absolutely brilliantly on the small examples that are used to market it.
I have been using it for two years, and fundamental bugs in the system have not been fixed in that time. (The code inspection tools in the debugger are close to useless)
The last time I updated it my computer spent over three hours with the installer running at 100%. What on Earth was it doing? Mining bitcoin?
A whole lot of things are clearly going very wrong behind the scenes
Nah, C++ is mostly frowned upon inside Apple. The open source projects (clang and Darwin) contain most of the C++ in the OS. Objective-C is the ubiquitous implementation language in Apple's macOS/iOS/tvOS/watchOS userspace code. It will eventually be superseded by Swift as the Swift runtime improves. All userspace projects and some kernel projects are built in Xcode, and most developers internally use Xcode to edit the sources.
If you are building high-performance, high-scale systems software (e.g. database engines), modern C++ is by far the preferred choice for new software projects and next generation systems. The notion of C++ being "useful mostly for legacy codebases" is not in evidence. The reality, for better or worse, is that there is no satisfactory replacement currently for C++ for important classes of software even if starting from a completely blank slate. I like some of those other languages, they just can't do the job in a reasonable way.
The reason modern C++ is still the preferred language for some types of software is that it is significantly more expressive in critical ways, which has a substantial impact on software robustness, maintainability, and performance. You could use those other languages, but it would produce a substantially worse product and/or codebase.
To put it another way, there is often no way to translate an existing elegant modern C++ codebase into those other languages without major compromises to either the codebase or performance. And for the kinds of applications where C++ is preferred, those compromises are largely unacceptable. Maybe some of those other languages will approach the practical expressiveness of modern C++ for this kind of software eventually, but not anytime in the near future.
This is not true. Nor is the post you're replying to, for what it's worth.
Rust and C++ are roughly equally expressive for high-performance, high-scale software. The reasons to use one or the other for new code have little to do with whether each language can do the job; clearly, both languages can. Rather, what dominates are factors like whether your build/deployment system is set up to handle one language or another, what your engineers are experienced in, whether you care about memory safety, etc.
Source: I'm one of the maintainers of Rust at a large organization you have heard of that very much cares about high-performance, high-scale systems software.
The learning curve of Rust should not be underestimated, IMHO. I do not know except by my own experience and "gossip", and would be interested in hearing from a bigger shop that has to deal with it.
Rust can make an experienced developer feel utterly clueless. The borrow checker is a very harsh mistress. Moving from C++ to Rust for a computer programmer with many years of experience in C++ must be a frustrating and humbling experience. The simplest things become so hard.
I love Rust, but I do not use it professionally (I would love to). I can clearly see that it is a step closer to what we have been waiting for, it may even be the destination. But I can imagine the pain of moving a programmer from 20 years of C++ into Rust. Becoming a novice again
> The learning curve of Rust should not be underestimated, IMHO.
Not sure how this is relevant in a conversation about C++, for which the notion of a learning curve is even hard to apply given that practically no one manages to write code that can be trusted to be free of basic defects in the language.
> Rust can make an experienced developer feel utterly clueless. The borrow checker is a very harsh mistress.
And rightly so. Rust is only unique in that you get the hangover before deploying the code in production. It's puzzling that some might see this as a drawback of the language.
When I started learning Rust after ~25 years of C++, I was quite productive after a couple of months. If C++ teaches you something, it's that you can be productive with a language without being fully familiar with it. After all, 25 years doesn't seem to be enough for learning C++.
The borrow checker is not such a big deal. You should have learned the basics in undergraduate CS in the context of concurrency and/or databases. If you have done shared data parallelism in modern C++ (let's say with OpenMP), you are probably used to similar reasoning.
Borrow checking and lifetimes do make some design patterns difficult to use, which is a reason you should not use such patterns in Rust. But there are almost always ways of achieving the same goals with idiomatic Rust. It's a bit like having to unlearn gotos when transitioning from BASIC to more serious languages and their fancy "structured programming".
> When I started learning Rust after ~25 years of C++, I was quite productive after a couple of months.
Stating that it takes 25 years of experience in order to become productive with Rust doesn't really sound like a positive note.
Keep in mind that your typical user of high-level programming languages already has a very hard time grasping the basic mechanics of C++, and Rust's memory management paradigm alone is renowned for having quite a steep learning curve when compared to C++.
FWIW I was productive in Rust after a couple of months with a background ~5-10 years of experience in primarily JavaScript and PHP (no prior low level experience). Rust does have a steep learning curve, but I'd argue that it's shallower than that of C++ (which puts shoots up in complexity as soon as you wish to include a dependency).
This is especially true if you are actually intending to write production code. There's no way I'd have comfortable releasing my C++ code to production after only 2 months, but my Rust code was completely solid despite my lack of experience in the language.
Learning curve is a temporary problem because Rust is pretty new and a lot of people need to begin ramping up at the same time. Hopefully we’ll get to amortize that across many years of projects, like C++.
> Moving from C++ to Rust for a computer programmer with many years of experience in C++ must be a frustrating and humbling experience
My experience was the exact opposite.
To write correct and safe C++ code you need to be tracking things like lifetimes and ownerships anyway (even in modern C++). Rust allows you offload all of that cognitive overhead to the compiler, which greatly simplifies things.
There was a short period of time needed to get used to the borrow checker, but coming from C++ I understood why it was complaining about these things so the errors didn't come across as opaque or confusing.
Honestly, if moving from C++ to Rust is frustrating for a developer not because of missing but because of borrowing, lifetimes and move semantics, it probably means that they were writing very "old style" C++. I write my modern C++ following Rust semantics as much as I can, and I think it's the right way to currently use C++ without incurring in slews of preventable issues.
Rust IS modern C++ in a stricter package IMHO. C++ still has some extra magic (constexpr, SFINAE) that in Rust is yet not doable or requires procedural macros, but the core language is definitely designed around concepts such as by-value and move semantics which are crucial concepts to use when writing modern C++ applications.
Rust const is the equivalent to constexpr in C++. As for other compile-time "magic", Rust macros are a much more principled approach to that feature set.
Rust const is still way, WAY more limited than constexpr in C++. You can't do basically anything in const Rust yet, while C++'s constexpr even supports memory allocations.
C++ is not memory safe, which is table stakes these days for any truly "high scale" software. Which is why most large-scale software projects have been written in Java, a memory-safe language, since the late 1990s (taking over from the previously common use of C++). And no, even the C++ Core Guidelines and "modern" coding style do not fully address this issue; they're way too clunky, whether or not legacy code is involved. Rust, even more so than Java in the mid-1990s, is uniquely positioned in offering better performance and safety than C++ and a lower complexity in development.
All big GPU and HPC related companies have ISO C++ people on their payroll, so I doubt they will care to add something else.
And NVidia rather uses Ada/SPARK instead of Rust for high integrity computing.
In regards to Java, while I do agree, there is still enough JNI being used there, hence why Project Panama, to improve such workflows where C++ is part of the story.
Increasingly feeling that Rust is like Elm: a language with novel ideas, teaching valuable lessons (a vocabulary for teaching and checking thread safety, documenting exclusive vs. shared mutability in the type system, arguably a vocabulary for teaching and checking memory safety, though that comes at a steep cost), yet so stubborn the community treats its values (avoiding shared mutability) as moral judgments of code, and the language and deliberately obstructs writing code outside of approved patterns (single ownership tree, exclusive mutability). struct{Cell...}& doesn't need to be harder to use than C++ struct{T...}*, but Rust keeps it difficult because the community views it as bad code design and wants to keep it hard. And *mut T lacks RAII unlike C++'s unique_ptr, and requires unsafe blocks in every dereference. As a result, people turn to unsound patterns like https://github.com/kimundi/owning-ref-rs, https://github.com/mcoblenz/Bronze/, and https://github.com/emu-rs/snes-apu/blob/master/src/smp.rs#L5... (and https://gist.github.com/Darksonn/1567538f56af1a8038ecc3c664a... raises questions about what exactly is sound or will be redefined as sound).
It's a good language to learn. I hesitate to consider it a replacement for asm/C/C++. Writing rust is hoping that the code you're porting to rust can adapt well to the restrictions, and if not, searching for esoteric and needlessly unsafe/verbose workarounds.
Not to mention that to embark right now on a fancy-language-of-the-week codebase could be a career ending (and/or even company ending) mistake. I mean, I still work regularly on C++ codebases that are >30 years old (no STL!) and are supported and extended and even switch companies from time to time. God knows how many "languages of the future" we've had in these 30 years.
There are literally millions of C++ developers out there. And that number is growing. There are new C++ projects started every single day. It will take a very long time for any other language to compete with C++. I agree that most biz software that doesn’t require high performance should be written in something else. But there are many application areas where C++ still completely dominates. Look at commercial games for example, browsers, JIT compilers etc. Yes Rust might be able to do a good job in those domains but it is hard to compare with the C++ momentum.
While I agree with the underlying point, I doubt that the statement “This leaves C++ being useful mostly for legacy codebases” is true. I see new projects started in C++ all the time in my industry ( automotive video essentially ). In the Open Source world, I see it a lot too. SerenityOS comes to mind. You can hardly call that a legacy code base. In Microsoft land, C++ still seems like the go-to language everywhere outside of .NET with new APIs still being created. There is some interest in Rust but it still seems early and it is not at all obvious that Rust will push C++ aside ( though I would love it to ).
Microsoft tried to convince all C++ developers to switch to C# and completely and utterly failed. It was amusing to see how quickly they switched back to supporting C++ after years of pretending that C++ had no future.
C++0x is one of the reasons Go was created. C++ was getting far too complex:
"For me, the reason I was enthusiastic about Go was just about the same time we were starting on Go, I read (or tried to read) the C++0x proposed standard. And that was the convincer for me." - Ken Thompson
Side topic: Didn't we have a is_const_eval equivalent in C? I seem to remember a dark magic macro doing precisely that on the lkml somewhere, but can't find it.
There is no compilation-time evaluation of functions and statements in C. You have constants, which can be expressions, but that's about it. Oh, and macros of course.
compile-time evaluation was introduced in C++11 and expanded in subsequent versions of the language standard.
Also, `const` values in C are not really evaluated at compile time, because they have by default external linkage so they are not really "constant", they are more like "readonly" or 'let' in Rust. They are always loaded from memory, and that's why #define is still king in C.
Doing
const int X = 33;
// ...
void something() {
int arr[X] = ...
}
works in both C and C++, but with a catch: in C++, X is evaluated at compile time (it has internal linkage), while in C this works only after C99 because it's actually a VLA.
That's a GNU extension that everyone relies so much on it's basically akin to a standard. You get a warning from Clang (or an error from GCC) if you ask for a more "standard" interpretation of the source:
$ clang -o cs cs.c -Wall -std=c11 -pedantic
cs.c:6:6: warning: expression is not an integer constant expression; folding it to a constant is a GNU extension [-Wgnu-folding-constant]
A = X,
$ gcc -o cs cs.c -Wall -std=c11
cs.c:6:9: error: enumerator value for ‘A’ is not an integer constant
6 | A = X,
| ^
In general, that's illegal ISO C and should always be rejected, but as you see that's not usually the case.
You might be able to do something truly arcane using GCC extensions and maybe the __attribute((error))__ thing but realistically it either won't compile or you won't notice unless it's too slow.
The compiler constant folds fairly effectively anyway.
What do you want to use it for? C++ uses it for the compile-time programming together with templates. Essentially C++ evolves into a language where you write a program that gets interpreted at compile-time to produce some code that then gets compiled. But I am not sure this is a good idea. It adds a lot of complexity, places many responsibilities that belongs into a compiler onto library writers, increases compilation time a lot, and - with all template expansion - causes a lot of bloat that hurts performance. It also makes debugging interesting. But it looks really good in microbenchmarks because you can create optimal code for special cases easily, I just do not see how this translates into real world performance.
Here, the b field is used uninitialized because the order of member initializers in the member initializer list is irrelevant;
what matters is the order of declarations in the class definition.
(A related warning, -Wreorder, can be used to warn when the order of member initializers does not match the declaration order.)
The order of initialization is the order of definition, i.e., a then b (because the definition order is `int a; int b;`). So initialization happens like so:
// implicitly, a = undefined;
// implicitly, b = undefined;
a = b;
b = 1;
So b is used when its value is undefined. The undefined value is assigned to a.
What confused me in their wording is that they seem to imply that the problem is: b would be left uninitialized, rather than: a depends on uninitialized b.
Your explanation, OTOH, is straightforward to read.
Mmm? The consequence of reading the uninitialized variable is that your program's behaviour is Undefined. There's no point worrying about this other variable named 'a', it's already game over.
It's not called "Temporarily unusual" behaviour or "Reliably crashing" behaviour or even "I bet it'll probably just skip that and do the next thing" behaviour, it's Undefined for a reason.
The distinction is helpful so that people properly understand what's going on with and what's wrong with the code in question (the context is helping someone who did not fully understand). You're talking about the consequences in terms of compiler output and code execution, and yes, the usage is the problem.
When they say “b is used uninitialized”, they’re referring to it’s usage in that snippet. It’s uninitialized when referenced as a value for “a”.
It’s pretty easy to read that text as suggesting that b would be uninitialized in subsequent code, but that’s (not true, as you suspect, and) not what it’s talking about.
It you are looking for news on C++20 modules support, then, sadly, there is not much progress since GCC 11. I've re-tested my modules examples[1] a few days ago with the GCC 12 snapshot, and while a few bugs have been fixed, the majority remain unfixed[2].
I'm looking forward to the full implmentation of C++20. I'm just a junior programmer, but I've just started playing around with modern C++ and it feels all more safe than I was initially planning. I was expecting more undefinded behaviour and memory leaks. Working in C++, at least for small scripts, didn't feel much more burdensome than Python.
Tangent: Is there a reason why C and C++ compilers are dev-PC-OS dependent for ARM targets? For example, if using Rust to compile for a Cortex-M etc, the workflow is the same for Windows and linux: Install the `thumbv7` target using a CLI command, then `cargo build`. I'm trying to build an OSS C lib now for the same platform, and the Windows instructions involve WSL or Cgywin.
The most likely reason in your case is the build system of the library you want to build uses some mix of POSIX shell script and GNU Make, which is ... hard to get right on Windows. It's not C/C++ specific, through installing a cross C compiler on Windows might involve more work than rustup add target (or not, if someone did the work and packaged the toolchain as .exe installer).
Rust only uses LLVM currently. WSL or Cygwin is because the compiler situation on Windows is a bit rough(VS doesn't support C fully), so most people use GCC there.
> but for actually assembling toolchains you generally only need one
Not if you intend to ship on multiple platforms. Having to run builds on the native platform or install a separate cross-compilation toolchain is incredibly annoying (and difficult to get right to the point that it's common to not even try). It would be a big usability win if C toolchains could get cross-compilation to Go or Zig levels of "just works".
This guy looks like he's implementing an entire new C++ compiler, but he seems unconcerned with making it open source or getting it to work on other platforms. I'm not sure what he's up to. https://twitter.com/seanbax
I worked on few projects in c++ many many years ago, so I don’t define myself as an expert in that language, but c++ nowadays scares me, looks like the language complexity have exploded and code looks like complex to me. All those templates … I have the feeling that languages like Rust have a chance long term to replace c++
Until they are 40 years old, with similar growth pain points.
I look at Java 18, C# 11/.NET 7, Python 3.10, and the knowledge about latest features, language and ecosystem changes across all major libraries for the last 25 years is hardly less complex.
I completely disagree. Java, C# and Python are all dramatically less complex than C++. And there is an additional issue: lack of knowledge about something in one of those languages might lead to a suboptimal implementation, but it is unlikely to lead to anything akin to undefined behaviour. As such, there is a sense in which you need to know everything about C++ in order to use it safely that isn't true of almost any other language.
>you need to know everything about C++ in order to use it safely
Well, you should know the libraries that you're using in C++, but I don't think that's any different in Python or Java. Granted, the mental model is more complex in C++ but that's the price you pay for the amount of control you get.
Also, isn't undefined behavior a lot easier to come across in Python since it's dynamically typed?
python doesn't have c style undefined behavior. you might get unexpected behavior, but that is very different from undefined behavior which allows the compiler to delete your hard drive and launch a nuke if it feels like it.
Why does it matter how Python 1 worked? Nobody is using that these days. In fact , in 2022 you can probably even get away without knowing python 2 either.
Well you at least need to know a whole plethora of things that can trigger undefined behaviour, many of which are triggered by code patterns that are idiomatic in others contexts.
This is very unlike language like most other languages where you can play around with little language specific knowledge and the worst thing that's likely to happen is a runtime exception.
I am not sure about that. Java has been around for some time now, but any Java developer can easily read code written 20y ago.
I find c++ syntax terse and hard to read. A good example is the well know boost library. Even back in the days when I was coding in c++ on day to day basis, I have always found boost code hard to read and reason about.
You can read the code, but are you sure you understand all the JVM implications of how that code changed and which versions introduced what behaviours?
I had the same reaction staring at all those new features.
Reading the code in that page, I felt as if I looked up only to find the night sky abuzz with otherworldly ships glowing in the dark. It made me anxious. And I wanted to run.
But now I'm wondering, is this my reaction because it's been more than 10 years since I touched any c++ or because the language got really complex? I'm curious what seasoned c++ developers think about this.
Frankly, a lot of the article is obscure corner cases that 99% of C++ developers will not encounter.
It's important that they're there, authors of very generic libraries may have to deal with them. But I'd much prefer to have seen something about modules in that list...
My feeling is that C++ gained features. These new features allowed people to easily fall into some until-then unknown traps. Now C++ is gaining features to make these traps more visible and avoidable. The problem: to become proficient, you now need to know the features, its traps and how to avoid them.
Swift gets weirder and more difficult, C++ gets better. Will the two lines intersect? Probably not, but I'm starting to wonder.
I wish C++ had a few more cosmetic and convenient things that I've gotten used to in Swift. 1. Properties with get/set/didSet blocks. 2. Non-nullable types, ie `T` and `T?`. There's probably no way to add those, even as a GCC-specific non-standard extension.
Years ago I worked on some C++ and the code had a lot of pointers to objects. Maybe it was not well written C++.
In Swift (and Kotlin and others) the compiler can prove that you never get a null pointer error at runtime. If you want something that can be null, the type is `T?` (short for `Optional<T>`) instead of `T`. Then there are various syntactically convenient ways of unwrapping it and dealing with the null case. Eg `foo ?? bar` means give me `foo` if it's not null, otherwise `bar`. Or `foo?.x` means: get the property x of foo, if foo is not null.
I haven't used C++ much in recent years. If there's an equivalent, I'd love to know about it.
This issue is caught and flagged by clang-tidy. Though technically the standard says it is in valid but un-specified state. Because of short string optimisation, the move might be possibly a copy, so one should not rely on the contents being empty.
Clang tidy covers only the most trivial use after move scenarios. It's useful coverage but isn't and never will be complete like the rust borrow checker.
No, you can absolutely use it (but you most likely want to clear() or assign an empty string to it before doing e.g. push_back as move does not necessarily clear the moved-from object - std::move(some_int) won't clear the int)
Also, uninitialized by itself does not mean invalid though ? For your example, I wonder if it would make sense to flag it: printf could be implemented in assembly or Fortran for what we know (a few popular libc implementations are done in c++ for instance), and as such I don't know how much sense it would make for its internal usage of the pointed value to be checked against the c++ rules. I'd assume the outcome would be different with std::format or std::cout for instance
My complaint is that it is too easy to create an object with uninitialized members by accident. On account of the syntax being identical. I guess its too late to add affordances there.
I suppose a definition of valid that prohibited uninitialized members would preclude lots of useful stuff like container and buffer types.
From the msan documentation [1], the flaw with my earlier example is that `printf` isn't instrumented.
And to address your other question, I don't know if msan can instrument a function implemented in assembly. It definitely can't deal with something it didn't compile as the instrumentation is added during compilation.
It seems that on godbolt the platform library also isn't instrumented because the equivalent iostream code is msan clean [2]. I suppose that makes sense as it's allowing you to pass arbitrary options to the compiler.
In summary, msan can detect these uninitialized reads but it requires quite a lot of fiddling.
`std::is_constant_evaluated` seems bananas to me - looks like a great way to end up with almost untraceable bugs, where the same function may or may not have bugs depending on whether its evaluated at runtime or at compile time. Are there good ways to run unit tests against both const and non-const evaluations?!
But then again, most new C++ features seem bananas to me, so I wouldn't read into it.
I'm saying a conditional branch that offers a different path of execution for a constant evaluation than for a runtime evaluation gives you a function that behaves differently in different contexts.
In Rust, for instance, constant functions have to evaluate the same in both compile time and run time - you can't have a different code path depending on which. If you want that, make two functions.
constexpr bool test_is_even() {
assert(is_even(0));
assert(!is_even(1));
// … more test coverage
return true;
}
int main() {
test_is_even(); // runtime coverage
static_assert(test_is_even()); // compile-time coverage
This lets us run all test cases at both runtime and compiletime. (The static_assert performs constant evaluation, and if an assert within test_is_even would fail, it won’t be a constant expression.)
But then you can't have generic functions that are efficient at run-time and work at compile-time ?
This feature is added to c++ not for fun but because if you can't have a run-time branch that will do some AVX-fu, or invoke some runtime function from BLAS or LAPACK, the whole "evaluate at compile-time" thing is... Not useless but not far either
Arguably, the only way to add zero complexity is to never add a feature. It's unclear what the point of that would be, given that it is trivial to stay on an older C++ version if this is your goal.
The C++ language designers have made a terrific language with the ergonomics of a four-fingered glove. Nim fits your criteria but doesn’t have the popularity of C++.
Nim has a variety of automated memory management strategies (more or less optional depending upon how much the stdlib and other libs matter to you). It has even recently renamed its --gc compile option to --mm to try to reduce confusion.
C++ and Rust are not so much "without GC" as "with optional, limited GC". Reference counting is a kind of GC, and is available out of the box in both C++ and Rust.
My point is, their are both so complicated because they are built around the idea of routine use without GC. Yes you can optionally have GC but it’s like saying you can tow a car. Yes you can, but the whole point of a car is to be self-propelled.
Similarly to how C++ and Rust fill an overlapping space I think Zig has shown tremendous promise developing a similar relationship with C in the GC-less language space.
If you're looking for a modern, GC-less go I think it'd be your best bet unlike, say Nim, which tries to be it's own language on the syntax side too much. Zig just feels like C, but with the semantics firmed up a bit.
185 comments
[ 3.4 ms ] story [ 223 ms ] threadI was interested in C++, not javascript.
It's basically as if Google and Apple don't really give a damn about keeping up with C++ standards, so they always get pushed on the back burner.
Most of those people behind, care about the LLVM infrastructure and not so much about upstreaming clang stuff or improving ISO C++ compliance.
But yes, a lot of LLVM users don't care about C++ standard compliance at all, for example because they don't use C++.
https://gcc.gnu.org/projects/cxx-status.html
https://clang.llvm.org/cxx_status.html
That world is not today’s world. Projects that would have been written in C++ in the past are often written in a different language now. This leaves C++ being useful mostly for legacy codebases, of which adopting new standards quickly is not so important.
Apple on the other hand mostly uses C++ in very restricted scopes such as DeviceKit which are very limited and can't safely use the entire language anyway. Xcode-shipped Clang and libcxx are often pretty old, too. They don't really need C++ that much above what C++03 already had, so it's clearly an afterthought for them.
One guess is because they didn't get what they wanted within the committee.
If I remember correctly some discussions on /r/cpp.
As for Apple, OP is right, Metal Shaders are based on C++14 dialect, IOKit/DriverKit use an Embedded C++ dialect, and for everything else there is Objective-C/Swift, and they only need enough C++ to use LLVM to develop them.
- A post about a C++ ABI break being voted against: https://cor3ntin.github.io/posts/abi/
I would not be surprised if google (or others in favor of breaking the ABI for the c++ standard library) would refocus on their alternate non-std std-replacement-ish library implementations (like abseil) instead given the lack of willingness to fix things in std proper from the committee.
Frankly, Google should fork C++ and create a new language without the warts and a new standard library.
That's how we got golang.
Another example of this shift would be that Bitcoin’s reference impl (2009) is written in C++, whereas Ethereum’s reference impl (2015) is written in Go.
[0] https://okws.org/
Go has more mindshare outside Google than on Google's critical infrastructure.
I meant a language by removing all the warts, not removing all the features. :)
Seriously, if Go offered manual/arena memory management and real generic programming - stuff like template template parameters, STL algorithms, auto-vectorization, etc - it could effectively replace C++.
https://www.youtube.com/watch?v=PFdKFoQxRqM
Now, one of the things which you may have noticed really annoys C++ proponents here on HN is when people say "What Rust does..." and well, maybe Vittorio should not have done that in his talk. But the reason he's saying it is that although Rust has very few new ideas it popularises lots of existing ideas from PL theory that were not seen in the kind of languages C++ developers had experience with before.
A few slides in, Vittorio explains that he's not offering language fragmentation or dialects, an ABI break, or yet more stuff every programmer needs to learn. Nevertheless, criticisms of Epochs generally say that this is language fragmentation, it introduces dialects, it's an ABI break, and every programmer will have to learn all this extra stuff so it's hopeless...
And of course there’s also WebKit and LLVM.
https://webkit.org/languages-staged-08192020
https://llvm.org/docs/CodingStandards.html#c-standard-versio...
Possibly an unpopular opinion, but personally I wish the C++ Standard Library was kept separate from the C++ language and have the C++ committee focus on the language features instead.
This is not an unpopular opinion.
I think reading it would convince you that the statement Google doesn't use modern C++ at all is false. It talks about modern features like CTAD.
I'm pretty sure people said that about C++ when Java became popular.
Rust seems like a fine language, Zig sounds interesting, and Go and Swift I'm not familiar with. But I don't really buy your argument.
I was part of one, whose goal was to replace a CORBA infrastructure based in HP-UX, with Websphere running on Solaris/Linux.
I'm not a Rust dev, but I am curious how things like epoll would work in Rust. In C (or C++) I place a pointer to a structure in the epoll `event.data.ptr` field. When an event is returned by epoll_wait() all the caller has to do is run a function on that instance in `event.data.ptr`.
It seems to me, that even with `unsafe`, you're not going to be able to do this in Rust unless all the code is unsafe. You cannot transfer ownership of the instance to `event.data.ptr`, can you mark the pointer or event structure itself as `unsafe`?
Why wouldn't std::mem::transmute (plus a little bit of hand-managed lifetime emulation) work here? It is unsafe, but doesn't require the unsafe modifier to be present on code beyond where the transmute happens. Unless by "all the code is unsafe" you mean related code is conceptually at risk of unsafety due to bugs caused by erroneous reinterpret-casts, then I think transmute should work here.
[1] https://github.com/tokio-rs/mio
[2] https://tokio-rs.github.io/mio/doc/mio/struct.Poll.html#impl...
It gets around putting a ptr into the event structure (that epoll will then return) by putting a tokenID into it instead (that epoll returns), that the connection_handler function will then use to retrieve the connection instance that it needs to work with.
IOW, in `C` I'd create an instance of a `struct connection_t` and `epoll_wait()` returns the pointer to the instance.
This way, it appears that an ID is placed into the event structure and the { ID : corresponding instance } tuple is stored in a hashmap. `epoll_wait()` returns the ID, the caller uses that ID to get an instance to work with.
Although, I could be wrong - I'm not a Rust dev.
Can you link to an explanation of, or an argument for, that claim?
The safety offered by Rust is not a thing to ignore. However modern C++ and the tooling has made enough progress in the area. It is extremely rare for me to allocate explicitly and in the couple cases where I do I always write deallocator first. It is ingrained in my nature along with some other related habits. Invalid memory access is also less likely with modern constructs. Along with memory sanitizers and practical experience with my own products I feel that Rust memory safety at this point does not offer much from my practical point of view.
I value very much time spent on compiling / building. From few experiments I made Rust is not any faster in this department. Rather the opposite.
As for C++ being a monster impossible to comprehend in its entirety. Agree and do not give a flying fuck. I am not there to explore language to its utmost depths. It is just a tool for me and nothing more. I do not get hung up on tools. As long as the tool lets me do my job with the reasonable ease (and subset of modern C++ definitely does) the rest does not matter. I do not feel inferior for not willing to spend the rest of my life trying to become Alexandrescu.
Still I love the utter madness that there's behind C++, and the fact you can basically do everything you set yourself to, no matter how crazy and weird it is, as long as you accept to put up with the madness. You can emulate a good 90% of what Rust does with traits if you really want to.
I suspect maybe because you love programming as a process. I write C++ (other languages as well) for living but I am my own company, so my primary concern is to deliver more while spending less. The language on it's own means zilch to me as long as it adequate.
"where I do I always write deallocator first" that sounds like good practise.
But software development is driven by marketers. Having the time to properly add in the features required for safety is important.
From a marketing perspective it is a waste of money. When a change needs to be made, some feature that once lived under the hood and needs to be "surfaced", using some pointer into a structure in an unsafe manner will take five minutes, properly assembling the structures, rearranging the code etcetera takes two days - those days come off the profit of the company (from the marketing perspective)
As a computer programmer it is fabulous to have the resources to do it safely. It is not the conditions that a lot of us (most of us?) work in.
User visible features. All that matters. Memory safety? What is that!
One example, https://iclg.com/practice-areas/cybersecurity-laws-and-regul...
For the last 20+ years I sit in the basement of my house where I design and build my products. Some for my company. Some for clients. Every once in a while I would get out and meet with perspective clients / subcontractors or for some meeting with existing ones. But it gets increasingly more rare and everything is done using Zoom/Skype/Remote Deployments/Couriers. The only reason I get out is mostly for fun - meeting friends, cycling, swimming etc.
Rust uses more generics in its idiomatic code than C++. If you're careful to split out your generic type impls to avoid excess code monomorphization, compile times can be manageable. Macro use brings similar concerns, but it's probably rarer unless you're relying on popular crates that need it such as serde.
I question whether those are actually competing in this same realm, for large organizations. Language adopotion is not just about the language, but also tooling, libraries, standard, etc which organizations have built up and rely on.
For example, at Apple C++ is used more internally than is exposed in public APIS. (I can't imagine the swift compilers performance scaling up to large code bases at this point.)
Can you speculate on other reasons, besides competition for the slower rate of adoption? Is it not as helpful as previous standards? Is it more difficult to implement?
It struggles on medium sized code bases.
And Xcode becomes flaky too, on medium code bases.
Works absolutely brilliantly on the small examples that are used to market it.
I have been using it for two years, and fundamental bugs in the system have not been fixed in that time. (The code inspection tools in the debugger are close to useless)
The last time I updated it my computer spent over three hours with the installer running at 100%. What on Earth was it doing? Mining bitcoin?
A whole lot of things are clearly going very wrong behind the scenes
The reason modern C++ is still the preferred language for some types of software is that it is significantly more expressive in critical ways, which has a substantial impact on software robustness, maintainability, and performance. You could use those other languages, but it would produce a substantially worse product and/or codebase.
To put it another way, there is often no way to translate an existing elegant modern C++ codebase into those other languages without major compromises to either the codebase or performance. And for the kinds of applications where C++ is preferred, those compromises are largely unacceptable. Maybe some of those other languages will approach the practical expressiveness of modern C++ for this kind of software eventually, but not anytime in the near future.
Rust and C++ are roughly equally expressive for high-performance, high-scale software. The reasons to use one or the other for new code have little to do with whether each language can do the job; clearly, both languages can. Rather, what dominates are factors like whether your build/deployment system is set up to handle one language or another, what your engineers are experienced in, whether you care about memory safety, etc.
Source: I'm one of the maintainers of Rust at a large organization you have heard of that very much cares about high-performance, high-scale systems software.
The learning curve of Rust should not be underestimated, IMHO. I do not know except by my own experience and "gossip", and would be interested in hearing from a bigger shop that has to deal with it.
Rust can make an experienced developer feel utterly clueless. The borrow checker is a very harsh mistress. Moving from C++ to Rust for a computer programmer with many years of experience in C++ must be a frustrating and humbling experience. The simplest things become so hard.
I love Rust, but I do not use it professionally (I would love to). I can clearly see that it is a step closer to what we have been waiting for, it may even be the destination. But I can imagine the pain of moving a programmer from 20 years of C++ into Rust. Becoming a novice again
Not sure how this is relevant in a conversation about C++, for which the notion of a learning curve is even hard to apply given that practically no one manages to write code that can be trusted to be free of basic defects in the language.
> Rust can make an experienced developer feel utterly clueless. The borrow checker is a very harsh mistress.
And rightly so. Rust is only unique in that you get the hangover before deploying the code in production. It's puzzling that some might see this as a drawback of the language.
Sky day one is very easy, yet it takes years to master.
Snowboard day one is going to be mostly about falling, unless you want into xgames, it is much easier to master afterwards.
It depends on which experience one wants to have.
Any conversation about C++ has to consider the costs of abandoning the ship
The borrow checker is not such a big deal. You should have learned the basics in undergraduate CS in the context of concurrency and/or databases. If you have done shared data parallelism in modern C++ (let's say with OpenMP), you are probably used to similar reasoning.
Borrow checking and lifetimes do make some design patterns difficult to use, which is a reason you should not use such patterns in Rust. But there are almost always ways of achieving the same goals with idiomatic Rust. It's a bit like having to unlearn gotos when transitioning from BASIC to more serious languages and their fancy "structured programming".
Stating that it takes 25 years of experience in order to become productive with Rust doesn't really sound like a positive note.
Keep in mind that your typical user of high-level programming languages already has a very hard time grasping the basic mechanics of C++, and Rust's memory management paradigm alone is renowned for having quite a steep learning curve when compared to C++.
This is especially true if you are actually intending to write production code. There's no way I'd have comfortable releasing my C++ code to production after only 2 months, but my Rust code was completely solid despite my lack of experience in the language.
My experience was the exact opposite.
To write correct and safe C++ code you need to be tracking things like lifetimes and ownerships anyway (even in modern C++). Rust allows you offload all of that cognitive overhead to the compiler, which greatly simplifies things.
There was a short period of time needed to get used to the borrow checker, but coming from C++ I understood why it was complaining about these things so the errors didn't come across as opaque or confusing.
Rust IS modern C++ in a stricter package IMHO. C++ still has some extra magic (constexpr, SFINAE) that in Rust is yet not doable or requires procedural macros, but the core language is definitely designed around concepts such as by-value and move semantics which are crucial concepts to use when writing modern C++ applications.
C++ is not memory safe, which is table stakes these days for any truly "high scale" software. Which is why most large-scale software projects have been written in Java, a memory-safe language, since the late 1990s (taking over from the previously common use of C++). And no, even the C++ Core Guidelines and "modern" coding style do not fully address this issue; they're way too clunky, whether or not legacy code is involved. Rust, even more so than Java in the mid-1990s, is uniquely positioned in offering better performance and safety than C++ and a lower complexity in development.
And NVidia rather uses Ada/SPARK instead of Rust for high integrity computing.
In regards to Java, while I do agree, there is still enough JNI being used there, hence why Project Panama, to improve such workflows where C++ is part of the story.
It's a good language to learn. I hesitate to consider it a replacement for asm/C/C++. Writing rust is hoping that the code you're porting to rust can adapt well to the restrictions, and if not, searching for esoteric and needlessly unsafe/verbose workarounds.
I don't see Go as a natural C++ competitor. Go primarily competes with Java and C#.
"For me, the reason I was enthusiastic about Go was just about the same time we were starting on Go, I read (or tried to read) the C++0x proposed standard. And that was the convincer for me." - Ken Thompson
17:45 mark here: https://www.youtube.com/watch?v=sln-gJaURzk
https://commandcenter.blogspot.com/2012/06/less-is-exponenti...
compile-time evaluation was introduced in C++11 and expanded in subsequent versions of the language standard.
Doing
works in both C and C++, but with a catch: in C++, X is evaluated at compile time (it has internal linkage), while in C this works only after C99 because it's actually a VLA.const int X = 33;
enum { Y = X };
The compiler constant folds fairly effectively anyway.
It's not exactly the same thing, but it's probably what you were thinking of.
Starting with C11, it's possible to implement it without any non-standard extensions: https://stackoverflow.com/a/49480926
It's not called "Temporarily unusual" behaviour or "Reliably crashing" behaviour or even "I bet it'll probably just skip that and do the next thing" behaviour, it's Undefined for a reason.
When they say “b is used uninitialized”, they’re referring to it’s usage in that snippet. It’s uninitialized when referenced as a value for “a”.
It’s pretty easy to read that text as suggesting that b would be uninitialized in subsequent code, but that’s (not true, as you suspect, and) not what it’s talking about.
[1] https://github.com/build2/cxx20-modules-examples
[2] https://gcc.gnu.org/bugzilla/show_bug.cgi?id=103524
[1] https://gitlab.kitware.com/cmake/cmake/-/merge_requests/7210
[2] https://gitlab.kitware.com/cmake/cmake/-/merge_requests/7210...
https://nwcpp.org/April-2022.html
https://dlang.org/spec/importc.html#__import
The same technique could be used with C++.
1. add some syntax to import a module
2. create another instance of the compiler to compile that module and return the symbol table
3. have the importer, when it doesn't find a symbol in the symbol table, to search the symbol tables of the imports
Changing the fundamental grammar is a step too far. Compilers can warn or reject bare statements in control structures if you want.
The most likely reason in your case is the build system of the library you want to build uses some mix of POSIX shell script and GNU Make, which is ... hard to get right on Windows. It's not C/C++ specific, through installing a cross C compiler on Windows might involve more work than rustup add target (or not, if someone did the work and packaged the toolchain as .exe installer).
The only thing missing are some atomic library calls.
Optional and not expected to be supported by every compiler out there, otherwise they would be part of ISO requirements.
clang-cl[1] does.
[1] https://clang.llvm.org/docs/MSVCCompatibility.html
LLVM is a library that happens to have Clang in front of it, whereas GCC still isn't really able to have multiple targets in the same binary.
Could probably be done but for actually assembling toolchains you generally only need one anyway so it's not that annoying most of the time.
Not if you intend to ship on multiple platforms. Having to run builds on the native platform or install a separate cross-compilation toolchain is incredibly annoying (and difficult to get right to the point that it's common to not even try). It would be a big usability win if C toolchains could get cross-compilation to Go or Zig levels of "just works".
I look at Java 18, C# 11/.NET 7, Python 3.10, and the knowledge about latest features, language and ecosystem changes across all major libraries for the last 25 years is hardly less complex.
Well, you should know the libraries that you're using in C++, but I don't think that's any different in Python or Java. Granted, the mental model is more complex in C++ but that's the price you pay for the amount of control you get.
Also, isn't undefined behavior a lot easier to come across in Python since it's dynamically typed?
Are you sure you master all language and library changes between versions, even minor ones?
What are the major differences between Python 1.5 and Python 3.10?
Very lucky ones, those that can do their work from scratch using latest version of everything, including the OSes where they get deployed.
Completely disagree.
This is very unlike language like most other languages where you can play around with little language specific knowledge and the worst thing that's likely to happen is a runtime exception.
I find c++ syntax terse and hard to read. A good example is the well know boost library. Even back in the days when I was coding in c++ on day to day basis, I have always found boost code hard to read and reason about.
Do you mean the code of the library itself, or code using that library?
Reading the code in that page, I felt as if I looked up only to find the night sky abuzz with otherworldly ships glowing in the dark. It made me anxious. And I wanted to run.
But now I'm wondering, is this my reaction because it's been more than 10 years since I touched any c++ or because the language got really complex? I'm curious what seasoned c++ developers think about this.
It's important that they're there, authors of very generic libraries may have to deal with them. But I'd much prefer to have seen something about modules in that list...
I wish C++ had a few more cosmetic and convenient things that I've gotten used to in Swift. 1. Properties with get/set/didSet blocks. 2. Non-nullable types, ie `T` and `T?`. There's probably no way to add those, even as a GCC-specific non-standard extension.
In Swift (and Kotlin and others) the compiler can prove that you never get a null pointer error at runtime. If you want something that can be null, the type is `T?` (short for `Optional<T>`) instead of `T`. Then there are various syntactically convenient ways of unwrapping it and dealing with the null case. Eg `foo ?? bar` means give me `foo` if it's not null, otherwise `bar`. Or `foo?.x` means: get the property x of foo, if foo is not null.
I haven't used C++ much in recent years. If there's an equivalent, I'd love to know about it.
E.g. in
str is never null, and always a valid object, because it's a value, not a pointer like in most GC'ed or dynamic languagesstd::string str1{"Apple"}; std::string str2 = std::move(str1);
Isn't str1 in an invalid (err, unspecified?) state and you shouldn't use it? It's not `null` sure, but it's not good to use.
It might not be null, but I can't do much more with it than I can with null. I need to assign something new first
I have a hard time understanding why "I could just be using a new variable" follows from "it won't have a useful value".
In Swift you are not allowed to declare a variable without assigning some value or nil to it before the current scope ends.
The semantics of c++ object initialization are such that a constructor will always be called.
What's better is that sanitizers don't detect this form of undefined behavior! (Clean on memory,address,undefined.)
https://godbolt.org/z/7jsxnMs8E
also relevant: https://i.imgur.com/3wlxtI0.gifv
Also, uninitialized by itself does not mean invalid though ? For your example, I wonder if it would make sense to flag it: printf could be implemented in assembly or Fortran for what we know (a few popular libc implementations are done in c++ for instance), and as such I don't know how much sense it would make for its internal usage of the pointed value to be checked against the c++ rules. I'd assume the outcome would be different with std::format or std::cout for instance
I suppose a definition of valid that prohibited uninitialized members would preclude lots of useful stuff like container and buffer types.
From the msan documentation [1], the flaw with my earlier example is that `printf` isn't instrumented.
And to address your other question, I don't know if msan can instrument a function implemented in assembly. It definitely can't deal with something it didn't compile as the instrumentation is added during compilation.
It seems that on godbolt the platform library also isn't instrumented because the equivalent iostream code is msan clean [2]. I suppose that makes sense as it's allowing you to pass arbitrary options to the compiler.
In summary, msan can detect these uninitialized reads but it requires quite a lot of fiddling.
[1]: https://clang.llvm.org/docs/MemorySanitizer.html#handling-ex... [2]: https://godbolt.org/z/Gsxsfn9GT
shows nothing on godbolt, but when run on my local machine yields the expected
But then again, most new C++ features seem bananas to me, so I wouldn't read into it.
In Rust, for instance, constant functions have to evaluate the same in both compile time and run time - you can't have a different code path depending on which. If you want that, make two functions.
Trivially:
How would you unit test this in a way that catches that only the constant evaluation is broken?This feature is added to c++ not for fun but because if you can't have a run-time branch that will do some AVX-fu, or invoke some runtime function from BLAS or LAPACK, the whole "evaluate at compile-time" thing is... Not useless but not far either
C++ is immensely complex. The amount you need to grok is very significant.
I wonder if that is somehow a necessary feature of a performant, GC-free, optionally low level language.
Could you, for example, create something with the simplicity of Go, (most of) the speed of C/C++, and no GC? What would it look like?
I’ve never written a line of Rust so no idea there.
The C++ language designers have made a terrific language with the ergonomics of a four-fingered glove. Nim fits your criteria but doesn’t have the popularity of C++.
If you're looking for a modern, GC-less go I think it'd be your best bet unlike, say Nim, which tries to be it's own language on the syntax side too much. Zig just feels like C, but with the semantics firmed up a bit.