#TuesdayCodingTips

2025-06-03

Tip 87 of #TuesdayCodingTips - Emplace into a vector of variants

`emplace_*` is an alternative to methods like `insert` or `push_*` in standard C++ containers. It allows you to construct the inserted object directly inside the container, passing all required parameters down to it, eliminating a needless copy/move along the way.

But what if you have a `std::vector<std::variant<Ts>>`? The interface is not flexible enough to control how to construct the variant object. There is however a hidden workaround.

Suppose your variant can be constructed from a cheap-to-construct type (trivial type, `std::monostate`, or similar). In that case, you can use that to initialize the new element and then invoke `std::variant::emplace` to override the element's memory with another type, presumably one that is expensive to copy or move.

Compiler Explorer link: godbolt.org/z/Yec1hvKzP

#tips #programming #cpp

C++ code snippet comparing the effectivity of pushing expensive type into vector of variants vs emplacing it vs pushing back cheaper type and emplacing over that memory.
2025-05-20

Tip 86 of #TuesdayCodingTips - Extendable logger pattern

I like my logs structured. If nothing else, I can log into a CSV file, load that CSV into Excel, turn on filters, and boom, I have a quite nice log analyzer tool. To get the maximum out of it, I need to be able to split my logs into as many columns as possible.

When creating a library where the user can provide their own logger implementation, you need to be very careful about the logger interface to minimize breaking changes in new library versions. Ideally, you want to be able to add new properties to the log without affecting existing logger implementations.

A typical interface method with one parameter per property won't do - every addition breaks the interface. What I like to do is wrap all loggable information in a struct and pass that to the logger interface instead. This allows me to add new properties with less fuss and evolve my libraries faster!

#cleancode #tips #programming

Code snippet that shows an example of an interface that breaks with every release.Somewhat better interface since all properties are encapsulated in a context struct.
2025-05-06

Tip 85 of #TuesdayCodingTips - Incomplete types and name demangling

While writing type-safe APIs, a "tag" type is often useful. It is nothing more than a forward declaration of a type that will never be fully defined, just for the sake of creating a template with a unique type.

Even without reflection, type-driven APIs can provide an opportunity to auto-generate (de)serialization code using typeid::name() utility. With two caveats:

You can't get the type info of an incomplete type
Unlike MSVC, both GCC and Clang will output mangled names
Luckily, both have a solution. While you can't get type info of an incomplete type, getting info of a pointer to an incomplete type is valid. You can trim the trailing star from the name. As for demangling, you can use the related ABI function (internally used by the c++filt tool).

Just remember to free your buffers, as said ABI function is written in a C-compatible way.

#cpp #programming #tips

C++ code snippet showing how to demangle C++ identifiers under GCC/Clang and how a "tag" type can happen.
2025-04-29

Tip 84 of #TuesdayCodingTips - C++ type trait for callable types

I recently asked myself: How do you make a reliable type trait for callable types so you can read their return values and call parameters?

The complexity lies in the fact that C++ has four distinct callable cases:
* A plain old function pointer
* std::function
* A class with an overloaded call operator
* A lambda

Some might argue that three of these are just iterations of the same concept, but lambdas have a compiler-specific/internal type, and custom classes usually don't contain all types for the call operator in their template (if they even have any).

The trick for defining the trait is thus in figuring out what the type of std::function would be should you construct it from your callable. Once you have that (through the use of declval and decltype), you can easily read the types from its template.

#cpp #programming #tips

C++ code showing a type trait for reading callable type's parameters and return type.
2025-04-08

Tip 83 of #TuesdayCodingTips - Curious case of NLOHMANN_JSON_SERIALIZE_ENUM

I recently debugged a case where code generated by NLOHMANN_JSON_SERIALIZE_ENUM failed at invariant assertions deep in the nlohmann_json library. When examined under a debugger, the data looked in line with the invariants, but there were different from what I expected.

Upon expanding the macro, I found a static const array in the generated function body. This was suspicious as I knew the code is running multiple serializations in parallel and that static array was the only shared state between threads.

But the C++ standard clearly states such initialization is thread-safe! Except that our project had a particular MSVC flag set - /Zc:threadSafeInit- (which disables thread-safe initialization), for good reasons I can't talk about.

Takeaway - the problem isn't always in the code itself. Trust your gut feeling and dive into the compiler flags as well!

#cpp #programming #tips

Expanded C++ implementation of NLOHMANN_JSON_SERIALIZE_ENUM macro.
2025-04-01

Tip 82 of #TuesdayCodingTips - C# exception filter

Ever found yourself in the situation where you have an exact same handling code for two (or more) selected exception types? C# has a nice way of deduplicating said code.

A `catch` block, processing a base exception type, can be optionally followed by a `when` clause, testing whether the exception in question is one of the derived types. A particular base exception can be used in multiple `catch` blocks, as long as at most one has no filter.

Furthermore, the filter expression is not restricted in any way, so you can interact with any object currently in the scope. If the filter expression throws, the exception is discarded, and the filter evaluates to false, moving to the next catch clause.

#csharp #programming #tips

C# code snippet demonstrating exception filter.c# snippet showing that you can use references to objects in scope in exception filter.
2025-03-04

Tip 81 of #TuesdayCodingTips - Pattern matching a C++ enum

For a particular C++ application I wrote, I wanted to send an enum over a string-based protocol and pattern match on it on the receiving end to make sure that all possible values were handled.

You can't pattern match on enums in C++, but you can do it on a set of types. That begs the question - how, without reflection, (de)serialize a set of types? And how to minimize the amount of changes needed and check at compile-time whether you forgot anything?

Serialization is mostly easy, you can even use typeid if both communication ends are compiled with the same compiler. A C++20 concept (or static_assert) can make sure all required types are part of the supported set.

Deserialization requires a bunch of template trickery but can be implemented in such a way you don't ever need to touch it again.

#cpp #programming #tips

C++ code demonstrating serialization through typeid with a concept for type safety, deserialization through template magic and then mattern matching on the resulting type.
2025-02-18

Tip 80 of #TuesdayCodingTips - C# lambdas and mutability rules

Mutability rules in C# are funky. While trivial types are passed into functions by value, they are captured by reference for their usage in lambdas.

That can lead to stupid bugs - what if you want to spawn a bunch of threads and each thread has to index into some array with an index corresponding to the loop control variable? By the time that thread executes, the variable will be out of bounds.

If you need to do something similar, your best bet is to copy the loop control variable into some iteration-local variable and use it in the lambda instead.

Interestingly enough, while Python suffers from the same issue, it:

a) lets you explicitly copy the variable in the lambda definition
b) a `range` loop creates a distinct variable for each iteration, so it's not a problem anymore

#csharp #programming #tips

C# code that prints a loop control variable in a delayed lambda.C# code that copies the loop control variable into a local variable so it can correctly print it in a delayed lambda.Python code that demonstrates that you can capture a variable by copy in a lambda declaration.Python code that demonstrates that a range-based loop creates an iteration-local variables anyway.
2025-01-28

Tip 78 of #TuesdayCodingTips - Many ways to read a file in C++

In C#, you can easily read a whole file using `File.ReadAllText` method. Obviously, things can't be as easy in C++.

You can choose the 'old way' where you pre-allocate a buffer to which you can read the data. This process involves seeking the end of the file and figuring out how big it is. I dare you writing this version from memory first time without an error.

Then there is the 'iterator' way. Just convert the stream object into an iterator and use that to initialize the string. Short, but not very memorable (not for me at least).

The easiest to remember (arguably) approach is to convert the file stream into a string stream and then easily extract the string contents from there.

#cpp #programming #tips

C++ code snippet that loads a file into a string through seeking to the end of the file, figuring its size and then reading into a buffer of that size.C++ code snippet that converts an input stream into an iterator that can be used to initialize a string.C++ code snippet that redirects internal buffer of std::ifstream into a std::stringstream and extracting a string out of it.
2025-01-14

Tip 77 of #TuesdayCodingTips - Multidimensional subscript operator

A quality-of-life C++23 feature has finally been integrated into Visual Studio (v17.12) after it was available in Clang (trunk) for quite some time. That feature is the support of the multidimensional subscript operator. In other words, you can overload `operator[]` to work with any number of arguments.

Furthermore, this feature goes hand in hand with std::mdspan - a non-owning multidimensional view over a 1D collection. This class is quite cool since storing 2D/3D tile data as a 1D array is a super-common micro-optimization technique in game dev.

Funnily enough, while Clang supported the operator long before MSVC, the trunk version as currently installed on Compiler Explorer doesn't have a support for std::mdspan.

#cpp #programming #tips

C++ code implementing a custom class with multidimensional operator[].A simple C++ sample using std::mdspan as a view over 1D array that behaves as a 3D array.
2024-12-10

Tip 76 of #TuesdayCodingTips - Type checking in Javascript?

When I want to prototype a simple GUI application, I often use plain old HTML + Javascript combo, because file protocol is cool, and setting up a node project is harder than I would like it to be.

But I would like to have some type checking in my Javascript code! Luckily, there is a cool feature in VS Code my friend @Ondřej Švanda told me about.

If you open your project as a workspace in code, you can then add a simple comment to the start of each Javascript file saying @ts-check. Then, if you write documentation for your functions, you can specify the types of parameters and return values.

And to top it all off, you can use a special @import comment to reference other files and bring them into scope, so the type-checking engine sees the whole picture. Even pressing F12 while a particular function is highlighted will navigate to that function's definition. Perfect!

#javascript #tips #programming

Example Javascript code with documentation and enabled ts-check.Screenshot from VS Code that highlights errors produced by ts-check.
2024-12-03

Tip 75 of #TuesdayCodingTips - Installing links with NSIS through CMake

I recently debugged a case where program shortcuts created by NSIS launched the program from a bad working directory. And since the NSIS installer was created by CMake, it required some backward-bending to fix.

To customize the working directory for links created through CreateShortcut NSIS function, you have to call the SetOutDir function before calling CreateShortcut. To configure this through CMake, you have to set the NSIS commands manually through CPACK_NSIS_EXTRA_INSTALL_COMMANDS variable.

Since that quickly leads to some CMake symbol-escaping hell, I’d recommend using the trick from the code sample to achieve the desired outcome. The trick relies on the fact that lists of strings in CMake are just semicolon-delimited strings.

#cmake #programming #tips

CMake code snippet that pushes multiple commands to CPACK_NSIS_EXTRA_INSTALL_COMMANDS, treating the variable as list and then converting that variable into a string by replacing delimiters with newlines.
2024-11-19

Tip 74 of #TuesdayCodingTips - Abstracting pipeline steps

While writing Azure DevOps pipelines, I often want to abstract a sequence of two or more actions into a function of sorts. For example, when publishing an artifact, I sometimes need to cherry-pick files from a given folder. This is normally done through the CopyFiles action, which cherry-picks the files into a staging folder that can be subsequently published.

To abstract this operation, create a template file that operates at the pipeline step level with a bunch of templated parameters.

You can call it at the level where you normally call tasks, just with the template keyword instead of a task. While running the pipeline, the template will be expanded into individual steps, so the pipeline logs will look like you didn't use any template at all.

#devops #programming #tips

Template YML file that acts as a function.Main YML file that "invokes" the templated file.
2024-11-12

Tip 73 of #TuesdayCodingTips - Resource Locator pattern

While catching up with Vittorio Romeo's blog, he mentioned a design pattern that immediately solved a problem I was dealing with in my C++ code.

Say you have a storage class for some resources, indexed by any sparse index (like strings). These resources are big so you wish to access them as (const) references. And let's assume you want to return expected/optional when the resource is not in the storage instead of throwing an exception.

That leads to a particularly ugly interface that you must use std::reference_wrapper in order to gain value semantics for references (required by expected/optional).

With the Resource Locator pattern, you split the interface into two methods. the first one is fallible and returns a unique resource access handle on success. The second is an infallible getter that consumes the handles. If the resources can't be deleted, this pattern can nicely streamline your code.

#cpp #tips #cleancode

C++ sample showing the example of a class with convoluted resource access method.C++ source showing a better storage class that uses the resource locator pattern.
2024-11-05

Tip 72 of #TuesdayCodingTips - Git worktrees

It is fairly common for me to have a bunch of open PRs at work. That requires me to have a bunch of clones of the same repo so I don't have to switch branches like crazy. But pulling changes on each clone gets tedious as the repo gets bigger.

That's where worktrees can come in handy. You clone the repository once and then through `git worktree add`, create a sort of shallow clone of that repo. They all share a single `.git` folder, so you're pulling the changes only once, but each worktree is a different branch, meaning a different version of the files. No two worktrees can be at the same branch simultaneously, which may be annoying at times.

Unfortunately, worktrees don't extend to submodules - those will each have their own `.git` folder.

#git #tips

Set of command-line commands to clone a repo, make a worktree, list a worktree and remove that worktree.
2024-10-22

Tip 71 of #TuesdayCodingTips - noexcept, vol 2

In tip 29, I shared how a noexcept keyword can be used in C++. Based on my recent experiences, I want to follow up with a few words of caution.

noexcept is more an API contract than an optimization. A transitive noexcept function still participates in stack unwinding. But because compilers can't diagnose misuse of the keyword, using it on transitive functions is a potential source of bugs.

I recently debugged a crash that appeared as an uncaught exception flying through a dynamic library interface. In reality, an exception escaped a noexcept boundary underneath and transformed into std::terminate. Very unpleasant to debug.

If you really want to use this annotation outside of leaf functions, either make sure to add static_assert for each function you're going to call, have a catch-all block, or make the noexcept conditional based on the signature of the called functions.

#tips #cpp #programming

C++ code showing various uses of noexcept - as an annotation, as a boolean predicate. It even shows how to use std::declval to get a reference to a type that might not be default-constructible.
2024-10-15

Tip 70 of #TuesdayCodingTips - JSON (de)serialization in C++

Many tips back, I wrote about JSON (de)serialization in C#. For C++, I bet every dev knows the brilliant nlohmann::json library at this point. But do you know how minimalistically can you use it?

The library allows for great deal of complexity and customization, but that is rarely desirable in a code that should be reserved for data models. Data structures that are subject of (de)serialization should be just stupid data objects with all members public and no associated logic.

nlohmann makes it very easy to work with such objects. The NLOHMANN_DEFINE_TYPE_NON_INTRUSIVE macro just needs you to provide the name of the struct and all its members and it will generate necessary code for you. The downside is that you can't customize the serialized names of the attributes.

For enums, NLOHMANN_JSON_SERIALIZE_ENUM works very similarly, with the added bonus of being able to customize those JSON names.

#cpp #programming #tips

C++ code showing how easy it is to use nlohmann::json.
2024-10-08

Tip 69 of #TuesdayCodingTips - Synchronizing stream writes

C++ streams are thread-safe but in a weird way. They guarantee that individual characters are printed correctly, but they might be interleaved with characters printed from other threads, which is undesirable.

C++20 came up with a standardized wrapper stream called `std::osyncstream` which wraps the target stream and ensures that whatever you are printing as a single string gets printed without any interleaving.

The usage of the object is not intuitive though. One would expect it to act similar to mutex - be shared across threads and be thread-safe on its own. This is not the case, the object is supposed to be created in each thread separately.

Nonetheless, a nice tool to keep around.

#cpp #tips #programming

C++ code spawning a bunch of threads that log to a shared reference to std::osyncstream. This usage is wrong, std::osyncstream is not threadsafe by itself.C++ code showing the correct usage of std::osyncstream - spawn individual instance in each thread.
2024-10-03

Google made available its NotebookML service (notebookml.google.com). It let's you upload a bunch of documents and then cooperate with GenAI on that context.

The most "ground-breaking" feature is the ability to generate Deep Dive podcast about your documents.

I've tried that on my coding tips and while the result is profoundly cool in the audio quality, the contents are a mixed bag. I could forgive the fluff content and some technical nonsense, the AI can hallucinate after all.

But what is really funny is like the male voice often proposes a topic A, then the female voice responds with something along the line "that's cool, explain it to me" to which the male voice slightly pivots to topic A.b, and then the female voice starts explaining topic A by herself.

Just listen for yourselves.

#TuesdayCodingTips #notebookML #google #ai #generativeAI

2024-10-01

Tip 68 of #TuesdayCodingTips - Don't return bools, return boolean enums

There are times when a general-purpose method returns some binary flag, perhaps to indicate whether it should be run again (like when reading from a stream).

Using a plain bool for that purpose is straightforward, but not clean code, as you know nothing of its meaning without referring to the documentation.

Instead, try using an enum for this purpose. In the stream example, it can have values named DataAvailable and EndOfStream. These are understandable even without reading the docs.

Furthermore, if you need to address some new, not-before-anticipated state, you can easily add it to the enum, perhaps even maintain backward-compatibility, unlike the bool API which is guaranteed to break.

#cleancode #programming

C-like pseudocode showing the difference between boolean and enum-based APIsC++ code showing how to specify underlying enum type.

Client Info

Server: https://mastodon.social
Version: 2025.04
Repository: https://github.com/cyevgeniy/lmst