/images/p1.jpg

Hi, I'm Tomasz

I'm a professional C++ software engineer with over a decade of hands on development experience with variety of technologies (mostly Linux & embedded systems). This is my blog.

Find me on social media

Why I avoid using `default` and inline functions in my class declarations

Sure, = default is great and convenient especially for destructors and other special member functions but when declaring a class that’s meant to be a part of a shared library’s interface I try to avoid using it and here’s my reasons why. TLDR Tip When writing an interface class, containing virtual functions, don’t use = default or include inline definitions in class’s header file to avoid vtable/symbols duplication across compilation targets that use the header.

#2 The state of C++ package management: The underdogs(?)

Welcome to the second part of the series about dependency and package management in C++ projects. This time I’m gonna focus on somewhat less popular solutions than the main three. Overview Let’s evaluate if any of these are worth the hassle. Hunter Hunter caters towards CMake. The way it works is really similar to meson’s wraps (with the only difference that it’s not built into CMake). Usage is fairly simple. You have to export HUNTER_ROOT to a location of choice.

Yet another post about dynamic lookup of shared libraries

This post is a quick reminder to self regarding specifics of RPATH, RUNPATH, LD_LIBRARY_PATH, LD_RUN_PATH and the lookup order. Refresher (a very short one) RPATH, RUNPATH - are entries in the ELF header, baked into the binary allowing the dynamic loader to lookup its shared dependencies. RPATH/RUNPATH can be specified directly, using a linker option (-rpath): g++ -Wl,-rpath=path/for/rpath If missing in the command line, RPATH can be set using LD_RUN_PATH variable.

#1 The state of C++ package management: The big three

In this post I’m gonna do a short overview of package management and vendoring solutions for C++. This is a controversial topic. Still, there’s no official standardised package manager however, there’s a plethora of solutions (some more mature than others) which I think solve the problem well (at least as far as I’m concerned). I planned to publish the entire overview in a single post however, there’s a lot of material to cover and eventually I had to split it up into multiple parts.

C++ quick tips: Overloaded virtual functions

Let’s suppose that you’re working with a virtual interface defined as follows: 1 2 3 4 5 struct I { virtual ~I() = default; virtual void process(int) = 0; }; Now, let’s have a class A that implements this interface: 1 2 3 struct A : I { void process(int) override {} }; So far so good. Now, let’s say you want to add an overloaded version of process in class B.

ZMQ event handling with zmq_poll

zmq_poll is used to monitor multiple sockets for events. The API is very simple. zmq_poll takes a pointer to an array of zmq_pollitem_t structures, the number of items in the array, and a timeout value in milliseconds. Each zmq_pollitem_t in the array acts both as an input and an output. The input part is used to specify the socket to monitor and the events to monitor for. The output part is used to report the events that occurred on the socket.

C++ quick tips: Full template specialisation and one definition rule

Recently I’ve been doing a lot of template meta-programming in C++. As we all know, when writing a class or a function template, the definition must be in the header file. This is because the compiler needs to see the definition of the template in order to instantiate it. There are some exceptions to this rule. The restriction doesn’t apply if you explicitly instantiate the template in the source file (and of course limit the template’s use to the set of types you’ve instantiated it with).