San Diego C++ Meetup – #44 – RxCpp and Boost.Asio

Today, Monday, November 14, we had our #44 San Diego C++ Meetup.

Unfortunately, there seem to have some issues in the posted link on meetup and many could not attend. Giant apology on this one. Not sure what happened and how but would pay extra attention next time (Dec 2022 here I come …).

Tonight, we discussed few interesting C++ Quiz questions, talked about RxCpp book from packt –

And also talked about Boost.Asio from the excellent Boost book:

here is the recording:

Enjoy!

Kobi

Modern C++ Coding Standard by Marcus Tomlinson – book review

By Yacob (Kobi) Cohen-Arazi

I have this habit of buying books. Like tons of books. Ask my wife, she’ll tell you. I think at that point she gave up.

I like to read what others think about the industry, about a specific domain. How do people see programming (especially C++) and technology from their own perspective.

So sometimes, I get to buy some not-so-familiar-books. This time it was “Modern C++ Coding Standards” by Marcus Tomlinson.

In the book, Marcus is saying that he wanted to share a handful of simple guidelines and best practices that he has been using in producing solid C++ projects over the past few years. And I do think he succeeded in this goal.

I’d start off by stating that the book is short. Easy to read in just couple hours. Not a lot of code snippets, so it’s pretty light. Very easy to quickly digest.

The book starts with one of the best features of C++ – RAII – C++ resource management mechanism. It explains the benefits of this important feature, not only in the context of Memory but also in the context of general resource management and cleanups at the end of a scope.

There are total of 3 parts in the book. Each has few chapters.

Part one (Modern C++ Coding Standards), Chapter One talks about how headers should be written. Couple things that I’m kinda disagreeing on, or at least on the fence:

  1. #pragma once – I’m leaning towards what the standard dictates vs the “less typing” approach. Yes, most likely you are working with a compiler that would have no issues with “#pragma once” but again – it’s not standard (yet?).
  2. Defining special member functions even though you do not have to. For example destructors. Even writing explicit =delete when not needed is something that I would not advise or at least I do not do it in my own code base.

Other than these two, there are plenty of well written points that I’m 100% on board with. I’m not going to list it here since the list is kinda big for a short blog post but I do suggest you go over it and see if you are aligned with each. I believe most of us would be.

Chapter two of the same Part One talks about organizing your cpp files. Again, plenty of good rules that I found very easy to read and digest. I believe most of the readers would find this part useful as well. As in the previous chapter, I have disagreement with one item – organizing the include headers. I’m in the camp of organizing the headers from the more general ones to the more specific ones. For example – your OS headers, then standard lib, 3rd party, your project. I find this order to be less disruptive and pretty solid when it comes to possible errors coming from your own project or 3rdparty headers.

Chapter three talks about Application Sources. Basically where your main() function lives. Lots of good suggestions like using std::future when appropriate, how to use std::async and similar. Just a reminder – the book is not going into details of the “why” but rather stays on the “trust me, you should do what I say/preach”. The bullets on auto, smart pointers and typedef vs “using” vs #define is spot-on.

Part Two is named “Language Agnostic Best Practices”. Chapter Four includes a set of very well written recommendations on how to construct your build system, automating the boring stuff (also great book … on Python), warning levels, static analyzer, version control, formatting etc… I felt like this is a really good list that should be applied to any Software project, regardless the programming language.

Part Three talks about “Templates & Compile-Time Programming”. Chapter five provides a short intro into Templates. I was pleasantly surprised to see C++20 code in this chapter. I.e. seeing concepts described as an advantage when used with Templates. Same warm feeling seeing C++20 related Lambda syntax. Overall, a very good Template introduction squeezed into just a few pages. While there are almost no real recommendations here in terms of coding standards but rather a C++ Class/Function Templates overview, I did find one good recommendation – Avoid specialization function templates and prefer overloading. Good one!

Chapter Six describes Template parameters. Again, not many recommendations but rather a good, concise overview on Template parameters. It covers Type Template parameters and also Non type as well as Template Template Parameters.

Chapter Seven, named “Beyond Templates” explains compile-time programming. It’s a very short chapter that describes the main idea behind constexpr and consteval (again, nice to see C++20 syntax).

The last part of the book provides an excellent summary of the points touched upon in the book. Basically, one can skip the entire first 86 pages and jump directly into the summary and just read, absorb and adapt (modulo the few disagreements that I and maybe others might have).

Overall, an affordably priced book, short (less than 100 pages long) but has good set of recommendations that should work for most, if not all, of us, Modern C++ programmers.

And Marcus – if you are reading this – great job! 🙂

Use case of utilizing std::set instead of std::map

Some time back I reviewed code that had the following design and data structure:

Now, the above is a struct but just imagine it could be a class with private/public sections, a beefy interface and data members.

The author(s) of the code wanted to place it in some data structure that can help retrieve an “Object” using a given “ID”. So they picked the following approach:

Pretty standard data structure. A {key, value} pair where the “key” is the “ID” of the “Object” and the “value” is the “Object” itself. This is not the first time I see such pattern. It is actually quite common in various code trees.

While looking at this piece of code I wonder, can we do better? The “ID” is part of the “Object”, and the requirements are to be able to insert/find values using std::map(*). The “Object”s are ordered by “ID”. My question is – Why do we need to repeat “ID” as a “Key” ?

Before we move forward, let’s compute the current cost:

This prints “sizeof pair 48, object 40, string 32” which means we pay an extra 8 bytes for storing an integer as the “ID”/”Key”. The same integer that is already stored in “Object”.

So the immediate thought is “yes“. We can do better. What if we eliminate the need for a separate “Key” and store the “Object”s in a similar container, that provides us the same requirements/performance(O(x) wise) but with smaller memory footprints?

We have something like this. It is called std::set<> and it has very similar characteristics to std::map<>. std::map<> stores std::pair<T1,T2>. It contains 2 types. std::set<> stores a single type.

So let’s give it a shot:

And we would like to have the same idea. We’d like to lookup number “5”. But std::set<> does not have a subscript operator (“[]”). It does however have “find()” function instead:

There are couple things we need to straighten out before we open the champagne.

First, by default, std::set<> requires less (“<“) operator to be defined for the stored objects. The compiler does not know how to compare “Object”s. We need to teach it. We can pass a compare function, we can use lambda or, we can just implement a simple member function that will help us to compare Objects by IDs.

This is basically fixing the major missing part. Remember that with std::map<> we had simple “int” as a “Key” and the compiler is very capable of generating code to compare “int”s. But not for “Object”s.

There is some wart here that requires discussion. If we want to write something like:

We need to be able to convert an integer to an “Object”. We can do it using a conversion constructor:

Notice the comment. We cannot make it explicit. In most cases, conversion constructor should be marked explicit, but if you actually need the conversion, you would have to pay this trade off. Otherwise, you’d need to write something less “natural” e.g.:

In my opinion this is a trade off that we would need to pay. Unless there are other sane options. For example I could think about having this non-explicit constructor in private section and having a get() friend function accessing it but I’m not sure this worth the effort.

That’s it. I saved you 8 bytes per entry. Keep the change and thank me later!

(*) std::map is probably implemented as a Red-Black Tree with log(N) to find something and O(1) to (re)balance it

Edit: September 29 2022

I recently realized that I could use Heterogeneous lookup and solve the issue I described with the find function. Here is the example:

And now, I can caall my find function in a very natural way:

Bingo!

Templates, Linking and everything in between

Last weekend, San Diego C++ Meetup hosted Andreas Fertig. Andreas presented his excellent talk on “C++ Templates”.

During his talk, one of the attendees asked a question that many, if not all, C++ programmers had asked at least once in their early life as C++ programmers. In this post, I hope it would provide answers to anyone that bumped into this issue before, and for those that haven’t yet 🙂

And the questions goes something like this.

While compiling and linking my C++ application, which happens to use templates, I’m getting a linker error.

To demonstrate this issue here is a simple example:

hpp file (include guard omitted):

Plus, here is a cpp file, that is added to compile line (e.g. via CMakeLists.txt or any other means)

And eventually main():

Just to discover the following linking error:

As mentioned above, I think all (most?) of us had this at least one time in our C++ programming career.

So what makes C++ Templates so special and makes it impossible for us to place a Template class definition in cpp file, compile it and try to call this function?

Before we answer this question, let’s take a step back and understand the compile/linker stages.

To put it simply, there are few steps to compile your C++ code. There’s a preprocessor step, C++ files to object files compilation step and finally, the linker will create a binary – executable or shared library. Creating a static library is just an archive of all of those object files (compilation units) and no linking step is involved in this case – so let’s ignore it for now (linking happens when exe/so is linked with your static lib).

Here is an example for a simple scenario, using non-Templated code:

And your main() would be something like:

And compiling the above would pass without issue. This is really a simple, vanilla example. Let’s inspect what we have on the file-system:

Note the getVal() that is part of the .text section. We have full definition in our compiled object file.

When main() is linked with this object file, the linker is capable of finding this symbol and all is good. Here is how main() object file looks like:

Note the *UND* kobi::MyNonTemplate::getVal() const – fear not! When creating the entire executable the Linker will find the definition and when you inspect the actual binary:

You see? all good. We have kobi::MyNonTemplate::getVal() const in the .text section and both compilation and linking stages completed w/o errors.

Now, let’s inspect what happened with the Templated one.

Here is the compiled .cpp file that contained that template member function definition:

Unlike the non-templated one, there is nothing interesting here!

getVal() does not exist here in any shape or form. So what happened?

Well, to put it simple, Template, and in this case class Template, is just a vehicle, a special syntax in the language for creating concrete types (or functions), concrete definitions. But for this to happen, one would need to:

  1. Ask the compiler to create, instantiate the class type. (same idea for functions btw).
  2. The compiler must have full visibility to the definition at the time of the instantiation. (unless extern template is used – this part is not covered in this article).

When we compiled the class Template in its own “compilation unit” and tried to instantiate this class type (+ calling a member function) inside main(), the compiler (at the point of instantiation) only had the declaration of the member function since we #include <> the header file. The compiler did not see the complete definition. It’s like there is no such definition!

Wait you say – but I have the cpp compiled. True, but remember, there is no spoon! There is no member getVal() function definition compiled into this translation unit!

It’s just bunch of code that no one instantiate when this specific “template” cpp was compiled!

OK. so what can we do? Few options that I will highlight here.

Define the body of the function in the header itself

There are couple ways you can define the function in the class Template header.

We want to do this so when another cpp includes this header, the point of instantiation has full visibility to the definition.

Or, you can leave the class with just function declarations, and have the definition somewhere outside of the class template:

If you check your compiled object with objdump , you’ll see that getVal() is now showing in your .text section.

Oh yes – using the above method, there is no .cpp anymore. You don’t need it and of course, you don’t need to compile it as a standalone .cpp file.

#include your cpp file in your header

Usually when I introduce this method to a junior C++ programmers, it really confuses them. How can you #include<> a .cpp file in your header. Well, I usually explain them that technically, I can #include<> (almost?) anything, and include it anywhere inside headers of C++ files. Not that every such #include<> would make sense, but yes, I can do it. Sue me!

What does it mean to have #include<> of one file within another file. It means the preprocessor will take the file mentioned in the preprocessor directive as #include<> and will just embed it in the overall buffer that will be fed later into the next compilation step. Don’t believe me? No problem. Run your compile line with -E (of course, no need to use -o option and similar) and you’ll become a true believer 🙂 You’ll see the output buffer of the preprocessor and if you have #include<> directives (and we assume that the preprocessor can find those files), you’ll see the content of these files in the output buffer.

So let’s put this knowledge into practice:

And here is your cpp, it would not have a #include<> of the header:

Again, if you check with objdump, you’ll notice getVal() is in the .text section.

But what if I really want to _compile_ my template cpp file?

I said above that it does not really make sense to compile a .cpp Template file. Well, I lied a bit. This is how you explain things in C++, you lie a bit and then, towards the end, you have a twist in the plot.

In some use cases, you might have the following requirements when working with external entities:

  1. You cannot release the definitions of your class (of function) Template. (IP reasons or you just don’t want others to see how bad is your code 😉
  2. You are OK to allow instantiation of only specific types.

In both cases, the mechanism is as described below:

  1. You write your class definition with only the function member declaration in the header.
  2. You write your class function member definition in a separate .cpp. This .cpp will be compiled.
  3. In the above mentioned .cpp, you instantiate this class Template with specific types. The compiler will generate full class type definition at the point of this explicit instantiation. (btw, this is applicable to non-member functions as well).

Example of such .cpp (#include<> of the header omitted):

I have explicit instantiation of this class type for int and float.

and example of usage:

Note that we cannot instantiate and use getVal() of double since we are back to square one with this type. There is no definition available for double!

Note that since the constructor is implicitly generated (and hence available to the compiler and to the linker) , instance of kobi::MyTemplate<double> would compile and link without issue. I just cannot call functions using this instance.

But there is one drawback with this approach.

One of the beautiful parts of class Template is that you only generate code that you actually use. So if, for example, I have other function(s) in the class Template, and I’m using the traditional way to write Templates (i.e. include the definition in the header and NOT having an explicit instantiate the entire class Template with a specific type), then in this case, objdump will only show me what is actually being used. Example:

If your main() does not invoke print() on some MyTemplate<> instance, this function would not show up in the object file!

However, when you explicitly instantiate this class Template with the syntax showed above:

Then, no matter if you are using or not using parts of the class Template, everything will be compiled and be part of the .text section.

Did anyone order code bloat?

Yes, print() will be there even if I did not use it in main() .

Conclusions

The traditional way to write and use Template code is to have the definition visible to the compiler at the time of instantiation. You can use it by inline-ing the definition in the body of the class, or outside of the class. Another approach is to write a .cpp (or any other extension) file that contains definitions of the member function definitions and #include<> it in the header. In all of the above, you do not compile a separate .cpp Template file.

Another approach is to compile a separate .cpp file and explicitly instantiate the class Template with specific types. These are the only types you could use with this class Template. Also, using this approach the compiler will instantiate the entire class member functions regardless of what you actually use. This is different from the traditional approach where the compiler is generating only parts that you actually use.

Function alias vs Function pointer alias

Last weekend (4/4/2021) I was sitting down and working on my San Diego C++ agenda for the 25th upcoming session.

One of things I really like presenting is few riddles from cppquiz.org

I stumbled upon this one: https://cppquiz.org/quiz/question/227 . Simple and easy one.

Here is the code in question:

And the question is what is the output.

So clearly the question is what does the following syntax mean?

Initially, the “using” part looked like an innocent typedef of a function pointer. But is it?

A quick check with cppinsights.io shows the following

Clearly this is not a function pointer typedef, and we are not defining any “f” as a data member.

Instead, we are actually defining a function named as “f” that returns “int” and takes no params.

So when does it look like a function pointer and when it is not?

Here is a small playground cppinsights.io.

And the gist of it is described in the following snippet: