32nd San Diego C++ Meetup

Agenda:

1. Welcome slides – goals we would like to achieve in San Diego C++ Meetup
2. C++ quiz
3. Do you know what your std::remove(_if) does?
4. Stackoverflow questions and discussions
4a. How does the C++ compiler evaluate recursive constexpr functions so quickly?
4b. How to check if int32_t number can fit in int8_t and int16_t?
5. Quora question discussion – Arrays, references and pointers
6. Book – Large-Scale C++ Volume I: Process and Architecture by John Lakos
7. Discuss few slides from walletfox website
8. Talk – My Quest for a Quick QuickSort

Event link on Meetup.


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!

= delete; // not just for special member functions

During the 29th San Diego C++ Meetup fellow C++ enthusiast and contributor to my blog, Kobi, brought up something interesting about deleted functions and I wanted to share this little gem with you…

To my surprise the = delete; postfix can be applied not only to special member functions like constructors or assignment operators, but to any free standing or member function!

Why would you want such sorcery you ask? Imagine you have a function like this:

void foo(void*) {}

On its own foo can be called with a pointer to any type without the need for an explicit cast:

foo(new int); // LEGAL C++

If we want to disable the implicit pointer conversions we can do so by deleting all other overloads:

template<typename T> void foo(T*) = delete;

Or the short and sweet C++20 syntax:

void foo(auto*) = delete;

To cast a wider net and delete all overloads regardless of the type and number of parameters:

template<typename ...Ts> void foo(Ts&&...) = delete;

Kobi found this on stack overflow of course 🙂


Example program:
delete.cpp


C++20 Concepts

C++20 introduced the Concepts library and the corresponding language extensions to template metaprogramming. This post will be a brief introduction to the topic for people already well versed in C++ templates.

What is a concept? Besides being a new keyword in C++20 it is a mechanism to describe constraints or requirements of typename T; it is a way of restricting which types a template class or function can work with. Imagine a simple template function that adds two numbers:

template<typename T> auto add(T a, T b) { return a + b; }

The way it is implemented doesn’t stop us from calling it with std::string as the parameters’ type. With concepts we can now restrict this function template to work only with integral types for example.

But first let’s define two most basic concepts, one which will accept, or evaluate to true, for all types, and another which will reject, or evaluate to false, for all types as well:

template<typename T> concept always_true = true;
template<typename T> concept always_false = false;

Using those concepts we can now define two template functions, one which will accept, or compile with any type as its parameter, and one which will reject, or not compile regardless of the parameter’s type:

template<typename T> requires always_true<T> void good(T) {} // ALWAYS compiles
template<typename T> requires always_false<T> void bad(T) {} // NEVER compiles

Let’s now rewrite the function that adds two numbers using a standard concept std::integral found in the <concepts> header file:

template<typename T> requires std::integral<T> auto add(T a, T b) { return a + b; }

Now this template function will only work with integral types. But that’s not all! There are two other ways C++20 allows us to express the same definition. We can replace typename with the name of the concept and drop the requires keyword:

template<std::integral T> auto add(T a, T b) { return a + b; }

Or go with the C++20 abbreviated function template syntax where auto is used as a function’s parameter type together with the (optional) name of the concept we wish to use:

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

I don’t know about you but I really like this short new syntax!

Concepts can be easily combined. Imagine we have two concepts we wish to combine into a third one. Here’s a simple example of how to do it:

template<typename T> concept concept_1 = true;
template<typename T> concept concept_2 = false;
template<typename T> concept concept_3 = concept_1<T> and concept_2<T>;

Alternatively a function or class template can be declared to require multiple concepts (which requires additional parenthesis):

template<typename T> requires(concept_1<T> and concept_2<T>) foo(T) {}

What follows the requires keyword must be an expression that evaluates to either true or false at compile time, so we are not limited to just concepts, for example:

template<typename T> requires(std::integral<T> and sizeof(T) >= 4) void foo(T) {}

The above function has been restricted to working only with integral types that are at least 32 bit.

Let’s look at a more complex example and analyze it line by line:

In line #1 we define a concept called can_add and define an optional variable a of type T. You may be wondering why the requires keyword appears multiple times. It’s because what follows after requires and is within curly braces {} is referred to as a compound requirement. Compound requirements can contain within them other requirements separated by a semicolon ;. If the expression inside is not prefixed by the requires keyword it must only be a valid C++ statement. However, what follows directly after requires without the surrounding curly braces must instead evaluate to true at compile time. Therefore line #3 means that the value of std::integral<T> must evaluate to true. If we remove requires from line #3 it would mean only that std::integral<T> is a valid C++ code without being evaluated further. Similarly line #4 tells us that the sizeof(T) must be greater than or equal to sizeof(int). Without the requires keyword it would only mean whether or not sizeof(T) >= sizeof(int) is a valid C++ expression. Line #5 means several things: a + a must be a valid expression, a + a must not throw any exceptions, and the result of a + a must return type T (or a type implicitly convertible to T). Notice that a + a is surrounded by curly braces that must contain only one expression without the trailing semicolon ;.

We can apply the can_add concept to a template function as follows:

template<typename T> requires can_add<T> T add(T x, T y) noexcept { return x + y; }

Template function add can now only be invoked with types that satisfy the can_add concept.

So far I have limited the examples to standalone template functions, but the C++20 concepts can be applied to template classes, template member functions, and even variables.

Here’s an example of a template struct S with a template member function void func(U); the struct can only be instantiated with integral types and the member function can only be called with floating point types as the parameter:

See the source code below for more examples.


Example program:
concepts.cpp


C++ Lambda Story, a book review

C++ Lambda Story
Everything you need to know about Lambda Expressions in Modern C++!
by Bartłomiej Filipek


I thought I knew all (or most) there was to know about lambda expressions in modern C++ until I befriended a fellow coder (and countryman) Bartłomiej Filipek, found his book, and after reading it I realized there were gaps in my knowledge and understanding of lambdas as one of the major features of modern C++.

I don’t want to give away too much of the book’s content so I will make this review brief. BartÅ‚omiej (Bartek) takes the reader through the entire history of callable objects in C++ starting with C++98 and function objects (or functors, objects which implement the function call operator), explains the usefulness as well as limitations of functors, then introduces us to lambda expressions as they appeared in C++11.

In the first and longest chapter of the book Bartek builds the foundation of knowledge by going over in great detail the syntax, types of lambdas, capture modes, return type, conversion to function, IIFE (Immediately Invoked Functional Expression), lambdas in container, and even inheriting from a lambda!
This gives the reader complete overview of the feature as it was first introduced in C++11, and prepares him/her for the following chapters where Bartek goes over lambda’s evolution through C++14, C++17, and all the way to the most recent iteration of the language, the C++20.

I found the book to be well organized into small bite-sized nuggets of knowledge that could be read, reread, understood and absorbed in a matter of minutes (similar to how Scott Meyers presents information in Effective C++).

C++ Lambda Story is not a book for people who are just starting to learn C++. In other words, it is not a C++ book one should read first. The content within the 140 or so pages is intermediate and advanced level of what the language has to offer. But it is a must for a seasoned C++ programmer as well as someone who already has a good grasp on the language.

You can find the book in black and white print on Amazon, a full color version, or a digital version on LeanPub.

To find out more about the author visit his website C++ Stories.

How to synchronize data access, part 2

Yesterday I wrote about How to synchronize data access, you should read it before continuing with this post, it will explain in detail the technique I will expand upon here. I’ll wait…

Alright! Now that you understand how a temporary RAII object can lock a mutex associated with an instance of an object, effectively synchronizing across multiple threads every method call, let’s talk about reader/writer locks.
R/W locks allow for two levels of synchronization: shared and exclusive. Shared lock allows multiple threads to simultaneously access an object under the assumption that said threads will perform only read operations (or to be more exact, operations which do not change the externally observable state of an object). Exclusive lock on the other hand can be held by only one thread at which point said thread is allowed to modify the object’s state and any data associated with it.

In order to implement this functionality I had to create two types of the locker object (the RAII holder of a mutex). Both lockers hold a reference to std::shared_mutex but one locker uses std::shared_lock while the other uses std::unique_lock to acquire ownership of the mutex. This approach is still transparent to the user with the following exception: a non-const instance of shared_synchronized<T> class must use std::as_const in order to acquire shared ownership ( const shared_synchronized<T>, shared_synchronized<const T>, and const shared_synchronized<const T> will always acquire shared lock; note that std::as_const performs a const_cast).


Implementation:
synchronized.hpp | synchronized.cpp


How to synchronize data access

I came across a post titled C++ Locking Wrapper shared by Meeting C++ on Twitter and it reminded me of Synchronized Data Structures and boost::synchronized_value so I decided to implement my own version as a learning exercise and possible topic of a future video on my YT channel.

The idea is simple: synchronize across multiple threads every method call to an instance of an object; do it in the most transparent and un-obstructing way possible. Here’s a simple example illustrating the idea:

The trick comes down to two things really: 1) Wrap a value of type T and its lock (in my case std::mutex) in a containing class and 2) Override operator->() to return a RAII temporary responsible for guarding the value.

I will add that this is perhaps a heavy handed approach to guarding data since I do not know how to make it transparent while allowing reader/writer locks, or synchronization of only some select methods. Perhaps some type system hackery with const and volatile methods could help here…


Implementation:
synchronized.hpp | synchronized.cpp


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.

How to implement a memory pool

Last week I explained what a memory pool is and how to use it. This week my lesson was about implementing a simple memory pool capable of fixed size memory chunk allocations. The pool preallocates a block of memory on demand, carves out equal sized chunks from it, and returns a raw pointer each time you call pool.malloc().
Memory chunks are described using a simple struct chunk_t and stored in a singly-linked-list; the struct has an internal anonymous union for size optimization: the same memory region can either represent the next pointer of the list’s node or hold user data.

P.S. Watch in HD, though I did increased the font size per your requests 🙂


Code from the class:
lesson_memory_pool_how_to.cpp
Cleaned up implementation:
memory_pool.hpp | memory_pool.cpp


How to use memory pools

In this week’s class I explained what memory pools are and how to use them to optimize frequent allocations and deallocations of objects. I also demonstrated how to overwrite operator new / operator new [] and operator delete / operator delete [] for a struct / class type.
The code for this class contains a simple benchmark which measures pool’s performance against the general-purpose allocator in C++ runtime. Notice how multi-threaded benchmark causes the pool to perform poorly (I suspect due to lock contention, though I did not yet investigate this). I didn’t even bother measuring array allocations; the memory pool benchmark causes massive fragmentation of the free chunks (by allocating all available chunks, shuffling them randomly, then freeing all) making continuous allocations virtually impossible without falling back onto runtime allocator.

Next week I plan on actually implementing a simple memory pool then again measure its performance against the runtime. Enjoy the video!

P.S. Remember to pick HD version of the video. It is also best to watch in full screen mode due to the font size used. I will try to remember to increase it during my next class. Apologies to anyone finding it hard to read the code.


Code from the class:
lesson_pool_allocator.cpp | lesson_pool_allocator_benchmark.cpp


How to detect memory leaks

During my last week’s class I discussed a source-code method of finding memory leaks in C++. What do I mean by that? Source-code method is not a way of debugging a process like one could do with Valgrind on Linux or Deleaker on Windows (which I’ve used recently and really enjoyed its integration with Visual Studio). What I am referring to is a combination of #define MACRO magic and overwriting the void* operator new. A technique to keep track of all your new / new[] and delete / delete[] statements and finding A) leaks due to missing delete statements and B) mismatches between array and non array versions of said operators.
Simply by including a header file in your source code you enable this tracing capability. Though it has a limitation: unlike Deleaker or Valgrind it only works for plain vanilla new / new[] operator; my solution does not support any other form of it.


Code from the class:
newtrace.hpp (C++17 or earlier) | newtrace.cpp | README.txt
Using boost::stacktrace:
newtrace.st.hpp | newtrace.st.cpp


How to implement a spinlock / event / semaphore

Multi-threading has been the theme of my previous two classes where I discussed thread-pools and producer-consumer queues. Let’s talk about the fundamental aspects of multi-threading and some of its most basic building blocks: spinlocks, automatic and manual events, and semaphores.
In this week’s class I will show you how to implement these building blocks using only standard C++ components: std::atomic_flag, std::mutex, std::condition_variable.


Code from the class:
lesson_spinlock_event_semaphore_how_to.cpp
Complete implementation:
mutex.hpp | event.hpp | semaphore.hpp


How to implement a producer-consumer queue

During my most recent class I discussed implementations of simple, multi-threaded, producer-consumer queues: unbounded (can grow in size indefinitely) and bounded (can only grow to a certain size). In short: the unbounded queue will block consumers’ pop() calls if it happens to be empty until a producer pushes something onto it. Bounded queue will do the same and in addition it will block producers’ push() calls if the queue fills up to its maximum capacity, unblocking only after a consumer frees up a spot with pop(). Finally I reworked the simple thread pool from last week’s class to use said queues, greatly reducing its complexity.

In the past I have implemented both types of queues (you can find it in my archives), but the bounded one used less than optimal approach: semaphores for counting free and occupied spots. This was costly because it required three std::mutex and two std::condition_variable objects. The one I implemented during this class requires only a single std::mutex and two std::condition_variable. The unbounded queue requires only one of each.


Code from the class:
lesson_queue_how_to.cpp


How to implement a thread pool

By popular demand, and at the request of my coworkers, this week’s class was about implementing a simple thread pool using only standard C++ components. It would have taken 1h-30m if I didn’t completely forget how to use a condition variable. It’s 2h long!
Bad std::condition_variable.wait(...) predicate caused a deadlock and I spent 30 minutes trying to figure it out. If you’re interested in the step-by-step implementation only then fast forward from 1h-15m-15s to 1h-45m-0s. Otherwise watch me reason through it. I eventually realized that the predicate should have returned true if the queue contained any elements, instead it tried to answer if 1 element was added to it.
For me the lesson was…

If you want to master something, teach it.

Richard Feynman

Code from the class:
lesson_thread_pool_how_to.cpp


Light-weight RPC framework

During my latest mentoring session with coworkers I was asked to explain how modern RPC frameworks work under the hood. What better way to illustrate this than to build one from scratch using components I blogged about previously (event objects, serializer framework, and TCP sockets).

Although not part of the video recording (which I will share later in this post) I explained that RPC frameworks generally work in two ways:

  • The client and server code is created at runtime and can be built on demand. Good example of this is the XML-RPC-C library: it contains no RPC IDL nor associated compiler/code-generator. It is simpler of the two.
  • The RPC methods of the server and associated client code is defined in form of an IDL, then ran through a code-generator producing almost all of the necessary client and server code. gRPC and Thrift are prime examples of this: both come with code generators and are very sophisticated. This was the type of framework I was going to talk about.

I did not design an IDL nor did I build a parser and code-generator for my students; there wasn’t nearly enough time for that. What I wanted to illustrate were different components which would have been generated by a modern RPC framework and how they would fit together. Starting with the client interface and code created to connect and issue calls to the server, serialization of parameters, network transport, command parsing and dispatching on the server side, actual command logic (this part would not be generated by a framework), and finally everything needed to send responses back to the client.

The starting point of creating a simple calculator server capable of adding and subtracting numbers would have been the server’s interface declaration using some form of an IDL:

This would then be processed by the framework’s generator to produce actual C++ code (or any other language) that would allow the programmer to easily connect, issue calls, and receive responses from the server:

Creating instances of the RPC server would be equally easy, but would also require providing the core logic of the server procedures:

In order for this to work a lot more code would have been generated then compiled against the static parts of the RPC framework: serialization, network transport, compression, encryption, authentication code, etc.
During my class I implemented the parts that would have been generated based on the desired set of procedure calls (the IDL), and reused code I developed for this blog in the past in place of the framework’s static parts.


Keep in mind that some of the supporting code I have already prepared before recording the class and I had it open on another screen, but the IDL based code I was coming up with on the fly, aka freestyling it 🙂
I figured it’s worth a mention in case my delivery appears less than… perfect.


Reworked and cleaned up code from the class:
Protocol: lrpc_proto.hpp. Client: lrpc_c.cpp. Server: lrpc_s.cpp.
Serializer: lsf.hpp. Network: socket.hpp. Event: event.hpp.


Case insensitive string, etc

The question of case insensitive strings has been, and continues to be asked a lot, and equally many answers can be found all over the internet. The go-to solution is to create a char_traits policy class with eq, lt, and compare methods implemented using std::toupper before comparing characters, then instantiate std::basic_string with it using istring = std::basic_string<char, char_itraits<char>> This works well until you try to use your new type anywhere near code designed with std::string in mind. Then what?

I guess what I am trying to say is that I never found a complete solution to this, so I decided to create one myself. I wanted the case insensitive string to play nicely and seamlessly with its standard counterpart. I wanted the ability to pass it as a parameter anywhere std::string is accepted; to convert between istring and std::string in both directions; push it to output stream; read it from input stream; compare it using all six operators, ==, !=, <, <=, >, >=, with std::string whether it appeared on the left or right side of the operation; and to declare literals of its type: "std::string literal"s.
In other words have it be indistinguishable from std::string except when comparisons are needed, like this:

The starting point was the character traits policy class mentioned earlier, but instead of using it with std::basic_string I inherited publicly from std::basic_string template configured with case insensitive traits policy; this pulled all its methods into the derived class scope, I only had to pull base class constructors:

All this derived class needed now was a constructor which would allow it to be created from any other type of std::basic_string as long as the character type was the same; implicit type cast operator to seamlessly convert it to std::string, and 4 comparison operators: == and <=> declared twice with istring as the first or second parameter. The constructor and comparison operators needed to be selectively enabled only for strings with different character traits policy, otherwise they would cause ambiguity and compilation errors. Final step was declaring operator >>, operator <<, and operator""_is.

P.S. Everything I just described also applies to wchar_t aka std::wstring.


The implementation on my GitHub page: istring.hpp, example program: istring.cpp.


Welcome, Kobi!

I would like to extend a warm welcome to fellow C++ enthusiast, and blog contributor, Kobi! Many of you know him from his Twitter account or as the organizer of San Diego C++ Meetup.

We have been exchanging likes and occasional comments on Twitter ever since I started this blog. He has always been encouraging and supportive in my blogging journey and I am happy he accepted my invitation to share knowledge and wisdom on this page (his first post).

Kobi will have permanent presence here posting news and updates about the San Diego C++ Meetup.

Welcome!

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: