The key is to realize C++ is not a language, but a federation of languages. You need to cherry pick a subset you what you want to use and stay disciplined. Otherwise, it is a mess.
The key is to realize C++ is not a language, but a federation of languages. You need to cherry pick a subset you what you want to use and stay disciplined. Otherwise, it is a mess.
Out of places that are vaguely keeping up with C++, the only thing I'd consider sub-setting that is commonly applied to C++, is disallowing exceptions and RTTI. There are at least decent reasons for this. Yes, there are places that have additional constraints (like "C with classes" style, i.e. no templates), but it's much more rare (and even more rarely technically justified).
Sub-setting should not be confused with the fact that in many cases, the language does not push you as hard down a specific path (for better or worse), yet it might be beneficial for a specific company in a specific domain to have a common solution for something, which results in the company style guide saying: "for this use case, use company_lib::foo, not XYZ".
Where I work we use pretty much all of C++, as appropriate, that is there is no blanket ban on anything, or official subset. That does not mean that e.g. there is virtual inheritance all over the codebase; that's a feature you should pretty much never need to use. Writing code appropriately and consistently can only ever be done via discussion and code review; no subset will ever magically fix these issues anyway.
Coming from C and thinking of everything in terms of pointers, it was already foreign enough, but the problem was that I couldn't find a definitive reference on how these features interacted and how to use them together successfully. So I gave up on C++. Maybe if I was motivated by needing it for a client project I might have gotten further, who knows.
I was lucky that i discovered C++ early and hence started with it as a "better C". I was not exposed to a lot of upfront complexity (eg. template shenanigans) thus making my learning curve easier. The big mistake people new to C++ make is trying to learn all language features and dark corners. Instead you should look at various aspects of the language separately and understand their applications. That way you learn how to model the problem domain using the appropriate syntactic features of the language. Here are a few different ways of looking at and using the language.
1) As a better C - You can define stricter types, control memory management using techniques like RAII/Smart pointers and enforce better modularization.
2) As an Object-Oriented language - Here you design class hierarchies and provide interfaces, domain libraries and frameworks.
3) As a Generic programming language - Here you define types and learn how to combine them using composition and delegation.
It might be helpful for you to read some of the older C++ books (Modern C++ IMO is more complicated since it mixes the language features in a free manner) to get at the root of "how to think in C++". To that end you might find the following useful;
1) Ruminations on C++ : A Decade of Programming Insight and Experience by Andrew Koenig and Barbara Moo - short chapters explaining various implementation techniques in C++.
2) Scientific and Engineering C++ : An Introduction with Advanced Techniques and Examples by Barton and Nackman - This book will teach you how to design in C++
3) Multi-paradigm design for C++ by James Coplien - Advanced book teaching you how to map problem domain concepts onto language features.
IMO, If you grasp the gist in the above books, you will understand "the heart of C++" and can easily pick up "Modern C++".
I am ambivalent on "Modern C++"(they have made it more complicated and invented a new language) and still ramping up on its features and nuances. Haven't really found any insightful book so far (except for "C++ Concurrency in Action" by Anthony Williams which of course is specialized).
However i recently found "Modern C++ Programming Cookbook" by Marius Bancila which seems like a very nice catalog of all the C++11/14/17 features. This seems to go well together with Stroustrup's book.
For 2D grid, here’s a code that I usually write when I need one, untested: https://gist.github.com/Const-me/7aee0ef4087d250cc9b82463988...
Thanks for the sample grid, I've bookmarked it, this'll be helpful for me and my son to understand where we took the wrong road in our implementation.
1. const correctness is awesome. I miss it so much in C# which I happen to code a lot as well. When you have a function which accepts `const Grid<int>& grid`, you can’t call resize() nor change cell values. If you’ll try, the code won’t compile. My given name is Const so I have bias, but still.
2. asserts. They aren’t even C++, these are from C, but IMO they have better ergonomics than C++ exceptions. They compile into nothing in release builds i.e. don’t affect performance, but in debug builds they trap to debugger right away, showing what exactly is not OK. For production code, sometimes it’s a good idea to use preprocessor trickery to turn failed asserts into scary log messages, in release builds.
P.S. It’s possible to implement much better resize(). When neither old nor new size is empty, the version on that gist will essentially turn old data into garbage. A better solution for that case, make a new vector on the stack, write a loop to crop or expand the items (e.g. calling std::copy_n), then call vector::swap to replace Grid::data vector with the newly built one.
The issue is that no matter how disciplined you are, others will be using a different subset of the features available and you end up using different "languages", even when everyone on your team is ostensibly writing "C++".
You can write generic imperative C++ by using lots of templates, OO code that looks like Java, low level imperative code similar to C, and even functional code.
I can personally say the same thing about Haskell or Common Lisp. Perhaps it's not that extreme, but there are many ways to solve problems in those languages. Even some funny jokes about Haskell exploit this:
https://www.cs.utexas.edu/~cannata/cs345/Class%20Notes/10%20...
Probably. How many of these powerful languages started out that way and received widespread adoption though? C++ was basically C with classes when it become big. C# and Java are complex beasts now but both gained popularity when they were much simpler.
Programming languages need to be comprehensible to your average programmer and not just a few elites.
I've noticed two strains in language design, which I internally call Scheme-style and Common Lisp-style:
Scheme-style languages are the trimmed-down languages, often built around a big idea which animates the rest of the design but not always; the defining concept of Scheme-style languages is always how much they can remove to get a pure design, a design which supports writing code in one style. Python, Smalltalk, C, and Scheme are all languages in this mold. Java is kind of a compromised Scheme-style language, or two of them (C and Smalltalk) rammed into each other at high speed, which also goes for Objective-C.
Common Lisp-style languages have mini-languages inside of them, or at least support multi-paradigm programming as a core design goal; you can trim a Common Lisp-style language into a Scheme-style subset, but you can't extend a Scheme-style language into something more Common Lisp-like unless you really are dealing with Scheme and have (hygienic) macros to use to add more syntax. C++, Perl, and Common Lisp are all Common Lisp-style; Unix shell is Common Lisp-style in practice because it encourages programmers to write in a bunch of relatively Scheme-style languages at once, all in the same program.
Note that both Scheme and Common Lisp have a conceptual core in the Lambda Calculus and axiom-like special forms. C++ lacks this and Perl doesn't really have it either, but most people don't write huge codebases in Perl.
Not much to add to the conversation here, but for some reason every time I read this it gets funnier and funnier.
But I do like your breakdown, it’s what I’ve been thinking whenever I see discussions like this.
https://github.com/fiddlerwoaroof/objc-lisp-bridge#type-dire...
(for a whole program look at: https://github.com/fiddlerwoaroof/objc-lisp-bridge/blob/mast... )
.. and then ensure that all suppliers of source code into your project stick to that subset.