Thursday, March 16, 2017

C++ tips, 2017 Week 8 (20-Feb - 26-Feb-2017)

This is part of my weekly C++ posts based on the daily C++ tips I make at my work. I strongly recommend this practice. If you don't have it in your company start it. 
List of all weekly posts can be found here.

1. bitset

std::bitset is a container for bits. Unlike the infamous std::vector<bool> it size is set at compile time so bitsets with different sizes are different types. It is designed to replace C-style more-<<,>>,|,&-than-program-expressions storing of binary flags in a long for example. It has operator[], bound checking tests, evaluating if all, none or any of the bits are true. It can also count the bits set to true so if are asked during an interview "How to count the true bits in a sequence of chars?" you can show the depth of your STL knowledge by answering something like "Well first I'll use std::bitset::count to write the most readable solution, then use it for baseline and then use std::array<char, 256> with precomputed number of bits for each index"

Let's see an example:
2. mutable

The mutable keyword is used in two cases:

lambda-declarator - this allows the captured by value objects to be changed and enables calling their non-const member functions during the execution of the lambda. As we know lambdas are syntactic sugars for a class with compiler generated name and operator(). When capturing by reference the compiler creates member references to the captured objects. When capturing by value it creates normal member variables and copies the captured ones into the member ones. The operator() is const by default and that is why we can not change captured by value objects or call their non-const members functions. The reasoning behind this behavior is that the lambda should be expected to produce the same output every time it is called - calling it should not change its state by default.

mutable just removes that const and we are free to have lambdas with immutable state (with a counter and for example) that changes every time we execute it.

The other use of mutable is to specify that a non-static class member does not affect the visible state of the object and thus is allowed to change even if the object is const. Typical usage is caching or applying it on a mutex for thread safety.

Thread safety and const/mutable is a big topic that I wan to cover in more detail (read: confidence in understanding is low and I want to understand it better before trying to explain it) but in short, the Standard Library expects calling const member functions on an object to be thread safe and if you have mutable members it is your responsibility to make them thread safe

3. Ranges

Ranges library a library by Eric Niebler designed to extend the STL to work better and ... work at all with ranges. Currently the standard library works with begin- and end- iterator which is a convenient way do describe a range but it is an overspecification and as with any overspcification it what we can do with the range itself.

The simplest example:
We pass the vector(a range) to the sorting algorithm not only the begin and the end of it.

However this is not even the beginning of it. What reasoning about ranges as a single entity enables is the use of operations on the ranges themselves and since applying anything on a range usually produces a new range we can apply another operation on the result and so on.

Since these operations are object themselves we can compose them producing a more complex operation that later we can use on a range. For example (taken from Ranges documentation):
Now imagine using this without auto.

It uses both lazy and immediate evaluation and another perk is the ability to easy work with infinite ranges - infinity is easy to work with if you do not try to process it all at once.

That is the very basic of it. Currently Ranges library is under standardization and chances are it will be in C++20 because it is already usable with all tree major compilers. 

4. Blog content clarification

I feel the need to add a little clarification of how I choose the content.

There is this bug in human cognition that we are biased to assume that everyone knows what we know. This is probably why most bloggers blog about what they've just discovered and not about what they know for 10 years. I'm far from assuming that I am knowledgeable about C++ enough to think that I am in position to educate the community about anything.

So what I do is to use blogging as a way to feel the gaps in my knowledge. I have a backlog with topics that are candidates for a tip which are collected mostly from things that I know exist and probably used them but do not know very well. Plus some topics that I know and feel that will make a good tip. But almost all of the things I write about I have to do an additional research. And this is the personal gain for me.

Views, likes and shares are important of course - they boost my self-esteem and motivation as I feel I'm contributing to the community but nevertheless keep in mind that most of the topics I have to research before writing them. That means there will be probably mistakes, gaps in description (as I try to keep them short too, part of the format) but eventually I'll write something very stupid and everyone will realize what a big noob I am (a.k.a. imposter syndrome).

I'm writing this clarification for two reasons - first is to be able to say: "Well I warned you" when the inevitable noob revelation event happens. Second, to hopefully inspire other people to overcome their imposter syndrome and to not let their gaps in knowledge stop them from blogging, sharing, contributing to the community, etc.  Only the fear itself is real.

No comments:

Post a Comment