Learn C++ the Hard Way Finally Progressing

I failed my first attempt at a great rewrite of this site.

By Zed A. Shaw

Learn C++ the Hard Way Finally Progressing

Hey, I'm running a 15% off sale on all of my courses, including my Epic Supporter Pack which gives you everything I've made or will make.

I am finally back to working on Learn C++ the Hard Way after about 1.5 years of being stuck on it. About 2 weeks ago I had a revelation that totally changed my aproach and unlocked my approach to the course. After that I had drafts of Module 1 and Module 2 within a few weeks. Keep reading for more about what I changed and why it's working.

What Stopped Me

The reason I was blocked in the C++ course for so long is I could figure out a way to explain:

int age = 0;
cout << "How old are you?" << endl;
cin >> age;

The amount of Object Oriented Programming going on here is far too much to explain to most beginners. I could have just said, "Trust me bro," but the problem then comes with how you clear the input when the user enters an error:

constexpr auto max_size = std::numeric_limits<std::streamsize>::max();
cin.clear();
cin.ignore(max_size, '\n');

Yes, clear() doesn't .... clear the input it...clears the error, and then there's no function to clear the input buffer so you have to cobble together this pile of WAT to actually clear the input buffer. That's a lot of fairly complicated code for something so simple. Definitely too much going on for just Exercise 19 where I just want to do some basic inputs.

At that point I was stuck. How can I teach a beginner a language that requires a Ph.D. in Object Oriented Programming just to read a line from the keyboard?

Grug To The Rescue

Last month I was streaming on Twitch and was joking about the amazing Grug Brained Developer essay when it hit me:

Wait, Grug's totally my C++ style. Wait, why don't I just teach everyone else Grug Brained C++?

You see, I have spent the last year or so paring C++ down to the absolute bone. I don't even use constructors that often. At some point in the last 3-4 revisions C++ made it so you don't really have to use very much C++. You can code it like a simpler language, and then only dip into the more esoteric parts when you need.

I like to think that there's two types of C++:

Grug Brained C++
This is where you don't use templates, use auto a lot, avoid inheritance, stick to structs because who's got time for private, and lean heavily on the standard library. This kind of C++ is actually fairly easy to use and still able to make complex software. It's the C++ for people who want to make something with C++, not make more C++ with C++.
Bjarne Brained C++
This is where you dive deep into all of the latest esoteric C++ features to create useful things for the Grug Brained users. It's the C++ for the library writers. The framework designers. The people who love spending a year using a template to add two integers and think everything should be a const expression.

What's beautiful about C++ is you can do both. You can spend most of your time keeping it simple as the Grug Brained rock smasher, then take a detour into Bjarne land to craft a CNC Machine that crafts better rock smashers.

This duality also means that you can learn the simpler Grug Brained C++ and you aren't restricted from the Bjarne style. You can start small, learn the basics with a simpler language, and grow into the complexity over time as you need it.

It Worked

Once I had the theme of teaching "Grug Brained C++" I was flying. I had most of the exercises worked out, and then it came time to implement as many GNU Coreutils as possible with only these features. I was able to crank out little versions of about 16 command line tools, despite avoiding most C++ features. I didn't use a single class, struct, template, or anything in the code. Just plain old beginner code and a lot of the standard library.

The idea of Module 2 is the student sits down and does a ton of little projects. I have them recreating micro versions of GNU Coreutils as small challenges. This is to boost their ability to conceive of a problem and code a solution. Then after this small set of exercises I have them spend some time creating as many small projects as possible with what they know.

Interestingly, you can get a lot done with this micro version of C++. I'd say it has more of a "Go feeling" than say, a "C style" because you're dealing more with gluing together APIs.

Isn't That Wrong?!

One thing I've found about C++ over the years is lots of people who do C++ have opinions on what's right and wrong, but everyone's version of "wrong" is someone else's "right". You talk to one C++ pedant and find out they're using C++11 with a mix of C++17 and one feature from C++26 but also they hate everything in the standard library because unordered_map "sucks." Talk to another and they're all C++23 all the way except they keep using std::move everywhere which completely destroys the RVO and NRVO optimizations.

The question really is, if not one person using C++ uses some kind of pure standard then can anyone really criticize how anyone else uses it? If you aren't religiously evicting patterns like std::move from your code every release then how you can criticize someone else who uses auto or avoids constructors?

For example, there's people who absolutely hate auto, yet you can use auto like this:

auto add(auto a, auto b) {
  return a + b;
}

It's called an abbreviated function template, and eliminates many uses of the keyword template. Yet, still you run into people who don't know this but have all kinds of opinions on using auto to simplify code involving complex template types? Or, they do know about it, and use it, but don't use auto anywhere else.

I guess I'm trying to say, "C++ correctness is in the eye of the beholder."

A Growth Mindset

What I think is, if I want people to get into this wonderfully weird language (that accidentally became the most creatively expressive language ever) then I have to simplify it down to a form that a beginner can comprehend.

A beginner can't comprehend a template friend function operator overload of a right bit shift.

A beginner can understand getline(cin, buffer) because that's just a function with two arguments.

Using something a beginner can understand at first doesn't mean they can't learn the more complicated things later. But, trying to get them to understand insanely complex things right away will guarantee they never get to the complicated things.

Current Status

Currently I have Module 1 and Module 2 drafted and ready to try. There's a bug with Clang 21 on Apple ARM that I have to resolve, but otherwise the course should work.

I've also laid out Module 3 but I'm in the coding phase. The way I work is I write the code for the module so all of the examples flow together and teach each topic, then I write the prose. The plan for Module 3 is to evolve a little game combat system to learn intermediate topics.

If you've the time to check it out, please do and report back to me either here or on the help site.

Thanks for Your Time

Once again, thanks for your time everyone, and I hope you're having a great day.

Zed


More emails we've sent.

Learn `C++` the Hard Way Finally Progressing

I failed my first attempt at a great rewrite of this site.

UpdatePublished Apr 26, 2026

The Great Rewrite Has Already Failed

I failed my first attempt at a great rewrite of this site.

UpdatePublished Apr 26, 2026

Epic Supporter Pack is Actually 15% Off Now

I gave the Epic Supporter the wrong sale price.

UpdatePublished Feb 28, 2026

The Great Rewrite Announcement

Announcing the Great Rewrite and some small changes to the UI.

UpdatePublished Feb 23, 2026