Assuming your screen is wide enough, the log is now much more readable:

If you don’t want to use Tampermonkey or similar, you may just open a Javascript console and enter document.getElementById("main-inner").style.maxWidth = "100%" for the same effect on the current page.

And of course, you could always copy the log to your favorite non-wrapping editor. 😉

To most C++ programmers — or at least those like me with a short memory — it may feel like bool has always been there. However it is still not present in its ancestor C (though C99 has _Bool), and it was only introduced in C++98. At that time, there was resistance to it, and examination of existing code (that was mostly using macros to simulate a boolean type) showed that preventing implicit conversion between boolean values and integer numbers would have broken a lot of things. So in C++, bool-to-int conversion is implicit, with false converting to 0 and true to 1.

I think that this implicit conversion from bool is generally not needed in “real-world” code, and that it is in fact a source of bugs.

For example, this tweet shows that because of this implicit conversion, a typo like in int x = 1 < y; (where < was meant to be the left-shift operator <<) didn’t raise any alarm.

In my coding experience, I cannot think of useful cases where I need to convert a bool to something else, apart from printf statements used during debugging — but for these, I have taken the habit of doing an explicit conversion anyway, e.g.: printf("b=%d", int(b));.

I can certainly imagine cases where a bool could be converted to 0 or 1, to be used in a mathematical expression, e.g.: a = useC * c, but I think this would be better expressed as a = useC ? c : 0.

Of course my experience is limited, and there may be genuine situations where this conversion could genuinely help — Please let me know. But I think that in these cases, making the conversion explicit should be trivial, and also useful by making it more obvious (a = int(useC) * c). Now, if such conversion is needed for a lot of your code, maybe it’s a sign that the bool type may not be the right choice.

My lazy-ish version of Burgundy beef, based on a recipe from my 1998 Petit Larousse de la Cuisine, which I brought with me when I moved to Australia. Sorry if I’m using the incorrect terminology, or explaining obvious things: I’m not a chef or even a good cook!

When it start to bubble, reduce heat to keep it simmering gently — not too hot, or some meat will stick to the bottom. Cover pot.

Let it simmer for at least 2 hours, the more the better, overnight is the best! Regularly stir and adjust heat if needed. Enjoy the aromas floating around the whole house!

Uncover, remove bouquet garni, increase the heat a bit for a stronger bubbling, but not full-on boil. Let it reduce (by evaporation – make sure your hood extractor fan is on), this may take 30-60 minutes. Try reducing by about 20% first, the sauce should feel a bit thicker, it should coat a spoon. If not sure, just try it like that in a meal, you can reduce more if you prefer it thicker.

If needed, season with salt and pepper to taste.

Serve with your choice of cooked vegetables. I think it goes best with mashed potato or rice. And some bread to get all of the remaining sauce off the plate! 🤤

Types don’t always contain what their name implies

Many C++ user-defined types may at time carry information that does not correspond to what their names say. E.g.: a Name object may be empty, which is not a valid name. All code that manipulates these types must handle such invalid cases, or trust that they have been verified elsewhere, which is a common source of bugs.

As an example, let’s consider a type that should contain a MIME string, e.g.: “audio/mp3”. A naive implementation may start like this:

Notice that there is no validity checks in the constructor, so any code that manipulates MIME objects will need to call is_valid() before trusting that these objects contain valid MIME data. But sometimes in the spirit of optimization it is tempting to write:

And this may well pass all your testing, because you have already tested MIME::is_valid() elsewhere so you will think you don’t need to check for invalid MIME strings in is_audio() again… Until you start getting crash reports from the field, when your users handle data of doubtful origin.

Ensure types are valid by construction

One solution would be to add validity checks in the constructor, and throw an exception when a bad string is provided. However this seems quite a strong action to take, as strings that are not MIME types are quite common in the real world, and it would force the user to handle the MIME validation before trying to create a MIME object. Also some projects prefer not to use exceptions at all (like Firefox).

My preferred solution is to hide the too-trusting constructor, and to instead provide a factory function that will verify the given string and will only create a MIME object when that string is valid. Any object generated from this function can now be trusted to always contain valid data.

C++17’s optional is of great help here as it forces the caller to do the right thing: The return value must obviously be checked for a valid MIME object, and that object may only be accessed when actually present. Afterwards, that MIME object may be copied, or just passed to other functions as a direct reference; and by contract there is no need for further validity tests.

If you cannot use C++17 yet (and don’t have access to a similar helper type), you could instead return a unique_ptr, at the extra cost of a heap allocation — which may make sense anyway for heavy objects.