- use C++, given that you stick to some convenient subset of C++ and can use stl
- stick with C and force them to do the basics, like linked lists and string abstractions over and over again.
I guess in the olden days really good students used to develop their own library of C abstractions, and reuse them with several courses; but you can't quite do that if you have C in just one course and what's the point anyway in this day and age ?This could happen for example if the data structure course was in python or java and later courses are in C.
Also you can do the darn list in many ways: single linked list, double, ring, with counter/without counter. All very important in this day and age when you should know to avoid them altogether because linked lists fucks up cache behavior.
Things like strings and pointers are nightmarish in C. Segfaults aplenty.
I've never encountered a segmentation fault since switching to modern C++. Just because you use C++ doesn't mean you have to use the entirety of it.
Welp, time to go back to BASIC everyone. Or Go
Powerful tools can be complex, who would have thought
Also, standards definitely shouldn't be inscrutable to programmers. Look at the ECMAScript and Go specifications, they're clear as day. Sometimes you just need to know exactly what your code is doing, and this only becomes more important in the low-level scenarios that C++ is often used for. I haven't read the C++ specification, but if it's as hard to read as everyone says it is, then there needs to be some other way to understand exactly what's going on. How else am I meant to precisely understand how my structs will be laid out, or which casts are guaranteed to be valid, or whether the language allows data pointers and function pointers to be interchangeable?
It doesn't, unfortunately it just adds to the complexity.
Take for example, `auto`, added in C++11. If you don't have to support C++98 or C++03, the use of `auto` significantly simplifies many workflows and is often strictly better with less mental overhead.
When writing code, yes, but in my experience, it can also make interpreting what code that overuses auto is doing (especially what variables are and what functions return) an awful lot harder in many situations, and you end up jumping all over the place to work out that "auto result = ..." is actually "uint32_t result = ..."
That's one of my personal pet peeves about more modern C++ (and other languages to some extent like Rust): they seem to be more optimised for writing code quickly (which generally only happens once), not understanding it later (i.e. you didn't write the code someone else did) and maintaining / altering it in the future, which generally happens a lot more over code's lifetime.
I could have easily used Go or Swift as examples instead.
And to be clear, these new languages are in general improving things a lot, but I just worry there's an over-emphasis on "being able to do a lot of complex stuff which very few syntax / characters", which I don't really fully agree with (at least for large complex long-term projects).
That's not to say I'm right, but in my experience of programming over 15 years in everything from ADA, C, C++ to Java and Python, at least on large projects, the speed at which code was created was very rarely that important. Getting it right, bug-free and performant was generally much more important. In some cases newer more-condensed syntax can definitely help, but in others, it can cause trouble.
Code is read much more often than written, and most newer languages optimize for convenience rather than readability.
In my view Rust is actually pretty verbose compared to other new languages, and feels a bit cumbersome to write. Technically it could be made quite a bit leaner syntax-wise.
I just wanted to point out that Rust and the Rust community often share your view and want to optimize for readability as well. There actually was a lot of heated discussion last year around proposals that suggested reducing readability for convenience.
That's a lot better to go on than "auto".
That's what auto fixes. It avoids coupling the concept of iterating from the specific type of the iterator which isn't important.
Similarly auto helps you achieve DRY. 'auto myFoo = std::make_unique<Foo>();'. The type wasn't removed, it just wasn't repeated twice.
But at this point auto, or things like auto, exist in nearly every major language. So you'll need to teach best practices for working with it at some point. That's a general thing that's everywhere.
But knowing if something is a base type, a reference, a (smart) pointer, or an expensive-to-copy class/struct is very important when writing high-performance efficient code. Being able to see this at-a-glance by the type in the code in my experience helps tremendously with understanding what the code's doing and the implications in terms of data passing / transfer and understanding how that section of code interacts with other parts or could be changed to do other things.
I also think it allows people to be a bit sloppy and not care what's going on (i.e. with regards to whether it's by-value or by reference, etc) as they don't fully need to understand the code, and again, in high-performance computing where you seriously care about processor cycles and memory allocations, this can make a big difference if you're not careful.
Please keep it civil. I'm sure you could refute the GP without expressing contempt.
This is a ridiculous argument. The entire point of the post was, as the author even noted, purely to deep dive into a rabbit hole, get super picky & pedantic about standards wording so that you can act surprised that copy constructors exist in C++ while it was completely glossed over in the identical C example of a struct copy initialization, and almost none of this is useful to know.
So don't fucking teach it and you'd have plenty of time to cover all that other stuff. Bam, problem solved. Ignore pre-C++11 entirely, and purely teach & use the new stuff which fixes all the complexity, and leave the rabbit hole for people that care about exploring the past.
Oh, and don't use standards wording because those are for compilers to use to implement the language, not for programmers to understand how to use it effectively. The only time it's ever useful to know the full definition of an aggregate type or how it has changed is when you want to write a blog post calling them crazy or complex. It's never useful to know when using the language. And if you have an object that cares to enforce it just
Tada, now the compiler will tell you if/when you violated the rule and you don't need to try and understand the full scope of the ruleset.