
enum WaveformType
{
WF_CONTIGUOUS_SURVEILLANCE_WITH_SZ2_PHASE_CODING,
WF_CONTIGUOUS_DOPPLER_WITH_SZ2_PHASE_CODING,
WF_CONTIGUOUS_SURVEILLANCE_WITHOUT_RANGE_AMBIGUITY,
WF_BATCH,
WF_CONTIGUOUS_SURVEILLANCE,
WF_CONTIGUOUS_SURVEILLANCE_WITH_RANGE_AMBIGUITY,
// Alternatively, as it's shorter and better matches the ICD:
CS = WF_CONTIGUOUS_SURVEILLANCE,
CDw = WF_CONTIGUOUS_SURVEILLANCE_WITH_RANGE_AMBIGUITY,
B = WF_BATCH,
CDwO = WF_CONTIGUOUS_SURVEILLANCE_WITHOUT_RANGE_AMBIGUITY,
SZCS = WF_CONTIGUOUS_SURVEILLANCE_WITH_SZ2_PHASE_CODING,
SZCD = WF_CONTIGUOUS_DOPPLER_WITH_SZ2_PHASE_CODING
};
This reply is mostly about some aspects of C++ that I dislike. I think I've been in denial about the impact of the inability for C++ to evolve: Although I've always wanted to try out Rust, Zig, etc. I felt insecure about whether I would have been just chasing trends. But I think my opinion on the matter is becoming increasingly clear. Its model for evolution is dysfunctional.
I don't like exceptions. For the same reason RAII is uncomfortable for me, because to raise an error in a C++ constructor you are forced to use exceptions. Error codes in C are painful in their own way, the language could be helping us so much more without being over-abstracted. Error handling is a good example, and here is a story:
In Go, if a function can fail, the client code always looks like this:
f, err := os.Open("filename.ext")
You are not forced to check err, but you are always forced to acknowledge its existence. Rust merely uses the type system to make the check mandatory.
I can understand how essentially forcing a nullptr check into the type system would turn people off, because sometimes it is indeed unnecessary. But I really appreciate it though. On the side, it's also nice that it's a monad.
With pattern matching being as first-class as it is in Rust, it's really not as much of a hurdle...
Additionally, I think the while let Some(...) or while let Ok(...) construct specifically somehow feels like it's providing much stronger guarantees statically than while ([some ptr]), even though it's the exact same after compilation, probably.
There were some discussions about the perforated standard of C/C++ and weak standard library of C++. Indeed, this is a good demonstration: Despite standardizing optionals and result types. It had to be watered down to be tied to exceptions, plus the fact that most of the code that you call as a client won't be using them. It's a mixed bag.
I can make a similar case about safe unions. std::variant is okay now, but it took a little too long to get here (compilers were Not Good at optimizing variant access for A Long Time). Rust enums, which are straight sum types from ML languages like Haskell, are tagged automatically, and integrates with the language through pattern matching. Zig's tagged unions are also better than std::variant.
int x = x + 1;
Indeed, this is always a bug, so why is this UB? So why wasn't this outlawed in C99, say? Again, the standard of the language knows nothing about memory models, so it's not like they needed to preserve some implementation's behavior. This is just one example out of potentially dozens, just meant to illustrate the point about UB and more generally the age of the language in the current year.
Something that I got unreasonably excited for is #embed in C23. Perhaps people are happy piping stuff around with xxd or ld, and have been doing it for decades, it's just not for me. Why does this have to so hard in C++? The author of std::embed (same author who pushed for #embed in C23) has had a terrible experience pushing for it in WG21, it's strictly superior to #embed for C++. (Although it seems #embed made it to C++26.)
This is really not so hard, other languages have it, and do so because there is no ridiculous baggage, and are genuinely trying to solve problems.
There is a regex library in the C++ standard library, it's std::regex. However, take it from someone involved with the committee: "it is currently faster to launch PHP to execute a regex than it is to use std::regex".
In short, the standard specified constraints that make it impossible to optimize the implementation, and because the big three decided to use inline templates, it is impossible to update the standard without forcing everyone to recompile from the ground up. Sounds like a crazy reason to prevent a language from evolving? Indeed it does. But fresh recompiles are also painful, and committee members have skin in the game! It is the design of the language in combination with fragmentation of toolchains that has lent itself for projects to be easily put in this position. Such a change is said to incur an ABI break.
By the way, std::regex is also kaputt with Unicode input. Because you were expected to use std::wregex (feel free to chuckle). Having seen the trouble it causes, UTF-8 by default in Rust just feels like it's worth it. A proposal that meant to extend std::regex with UTF-8 capabilities was shot down, because it also requires an ABI break! Despite the fact that the standard itself says nothing about the implementations, let alone the ABI. Despite the fact that the proposal was submitted with an implementation and usage experience.
In the meantime, std::regex remains undeprecated, despite boost::regex, the library that it's based on, outperforming it by an order of magnitude.
I took this from this benchmark. cppstd is std::regex. As a side note, the go-to default in Rust, the regex crate, is so fast, on par with hyperscan, in part because it implements the same SIMD algorithm "Teddy" from hyperscan.
"Couldn't you just use a regex library that isn't silly?", yea, it's what I'd do in practice. PCRE2, re2, hyperscan, etc are all valid options. But you have to put in the effort to reach for it, when others are having such great results with minimal effort (I don't even want to start a section about build systems, compared to cargo add regex). To claim C++ is a systems language and provide this sort of built-in facility is simply embarrassing.
I sometimes get an itch that regex compilation (from the regex string into the appropriate state machine, or whichever representation the regex engine uses) happens at runtime, when I know the regex string itself at compile-time. Indeed, CTRE can do it in C++ (and there are other preprocessor solutions like re2c and ragel). It's included in the benchmark above. But why did it take until 2017 for this to be a thing? Other languages that have stronger compile-time feature have had it forever! Because it required extensions to template metaprogramming in C++17, which leads to my next point of frustration.
In C, all you had were macros. I can't write complicated macros myself, and it's a always a pain to try to understand what the ones that I import are really doing. In C++, most metaprogramming is done with templates instead. For writing generics where you want to stick different types into containers, it's okay. For more complex scenarios, can we really pretend SFINAE is a good technique? Hacking with template eventually evolved into an embedded untyped Lisp inside the type system. Compile times became extremely infuriating. You didn't have an alternative for some of the template magic until very recently with things like if constexpr and concepts in C++20, which were themselves proposed as early as 2006. And it won't be until another decade (that is being optimistic) until the average C++ programmer knows what concepts even are. The syntax and keywords decisions are extremely beginner unfriendly, it all reads like nonsense, and once again, all because of the baggage.
Speaking of, have you used serde? Rust macros are closer to Lisp macros in that you get a stream of tokens, and certainly nothing like C macros.
"it is currently faster to launch PHP to execute a regex than it is to use std::regex"
LOL
time is not a profiler but I found it funny nonetheless