Note that you might choose to forbid anything that doesn't count as "modern C++", e.g. by enforced linting. Equivalently, you could instead have your compiler reject such programs (perhaps deciding to rip out various features and modules from the compiler, to avoid them being used). Either way, you're no longer writing C++: you're writing some other language (say, "C+++"), which is a sub-set of C++. In which case, you've done what the author suggested: deprecating C/C++ in favour of something safer!
So, you would mandate using Rust without "unsafe", then? Good luck with that.
C++ changed a lot over time, and the way modern code is supposed to be written is very distinct from "C with classes", but you still can do that if you want.
Many experts disagree with the way modern C++ evolves.
To say that modern code is supposed to use all the C++11-forward features or else it's obsolete is a massive bias on your part.
All that said, some parts of moder c++ like move semantics do really cut down on defects. People who go out of their way to use *all* of the new toys create codebases that make my teeth itch.
It meant not using stuff like templates, operator overloading, RTTI, exceptions, STL.
https://gist.github.com/caiorss/c7db87df674326793431a14006aa...
It looks pretty much nothing like a C program doing the same job.
A lot of those features were made to make C++ a safer language to use. Eg, with a construction like:
for(const auto& it : ast){
You can't accidentally walk past the end of the array by going one item too far. But C++ still allows you to write code the way you'd do it in C.You can forget the virtual destructor. Maybe the language is excused because it’s only a leak.
You could mess up the what() functions. (It’s not locally obvious that it’s correct in this code.) std::exception is fundamentally dangerous. Rust can get away with safely returning references like that because the lifetime is part of the function’s signature. C++, even modern C++, can’t.
Even the iterative example is only a bit safe. You can’t walk off the end by going one too far, but you can certainly mess up by invalidating the iterator in the loop body.
AFAIK, that's with a caveat of "unless you modified the array length within the loop" (looking at the gist, "ast" is a deque, so you can pop items from either end); IIRC, that C++ construct evaluates the begin and end only once at the start, instead of every iteration (unlike what you might do with "classic" C++ evaluating "it != ast.end()" every time), so it wouldn't notice the change. This is particularly annoying since C++ developers can be tempted to optimize a classic "for (auto it = ast.begin(); it != ast.end(); ++it)" loop into either the new-style "for (auto it : ast)" or the old-style optimized "auto end = ast.end(); for (auto it = ast.begin(); it != end; ++it)" loop, even though that would break the code if "ast.end()" ever changes within the loop.
(Since the initial discussion is actually about C and C++ versus Rust: in Rust, you wouldn't be able to modify the array within the loop, since the iterator is borrowing it, so this issue would be caught by the compiler.)
Checks linked resources
while(!ss.eof()){
ss >> token;
Can cause an endless loop (with finite input stream; for example in case of a read error). p >> x;
if(!p.fail() && p.eof()){
This way of error checking is correct for C++ but not nice (it or part of it can be forgotten with no warning--see below for an instance of it :P). struct stack_empty_error: public std::exception{
const char\* what() const throw(){
Missing "override" annotation here. Can easily fuck it up since overloads are allowed. return " ==> Error: stack empty." ;
}
};
auto x = _stack.back();
_stack.pop_back();
return x;
Correct in C++ but incredibly weird--typical for lowlevel languages that are far away from the user.Also, when I press Ctrl-D, I get an endless loop printing "EXPR+> stack". Typical C++ program...
void foo() { .. }
And others auto foo() -> void { .. }The second syntax was introduced for lambdas and decltype() usage for return types that depend on the parameters (due to look up rules), and some C++ subcultures now use it everywhere.
> auto main() -> int {
Absolutely no reason to masquerade main() in such a fashion!
It's a rule of least surprise, be it for user or fellow developer.
Does it really need to include <string.h>?
with constexpr etc, and std::move, and unique_ptr in use, many memory safety issues can be contained.
adding cppfront on top can make modern c++ even more memory safe.
Bold claim.
> With all due respect, this is coming from a Win32 API C programmer who happens to save the code in files with .cpp extension. In other words, not familiar with modern C++.
Edit: Ah, you said "know enough about modern C++", so yes, I agree and was arguing in the wrong bit of the thread.
Nothing you’ve said contradicts what I said.
And then other critics saying "Russinovich hasn't demonstrated skill with a machine gun so how can he say bayonettes are obsolete?"
I think they might have been going for the ludicrous image of sticking a bayonette onto the front of a fixed gun emplacement.
No, but he does need to "know enough about modern C++ to make the statement that we’re discussing".
Thing is in this case their advice regards the rifle.
It is nonsensical to say “the general can’t hit a moving target with the old rifle, so he should say nothing at all about weapons”. Which is what the person I replied to said.
I could throw a bunch of examples further. For instance how the changes made to rifles because of what Generals thought their engagement ranges would be hampered the western forces who had to fight in Afghanistan.
You should also be skeptical of a General who suggests we go all in on Drone Warfare and not worry about rifles at all.
TLDR, person in a strategic role is rarely the best to assess tactical tools, and will often attribute strategic failures on their tactical tools.
They usually have not been in the trenches for a good while at least (could even be like 20+ years since they've done any development), and they take the ultimate decisions for their whole company for all kinds of languages and environments they have had no experience with... (like a CTO that used to do C back 20 years ago, now having a say in the use of Rust or Node).
The sentence is indeed from a meme template[1], but I thought that my comment would stand on its own.