February 2025

Serialization by contract -- Alex Marmer

Alex shows in his small framework a different approach for serialization of data structures.

Serialization by contract

By Alex Marmer

From the article:

In any project, when a function is created for serialization, another function is created for unserialization.

Serialization by contrast uses another approach - a contract with name and data structures is declared, and then serialization and unserialization of the data are automatic.

Contracts for C++ explained in 5 minutes -- Timur Doumler

In this article, we briefly explain everything you need to know to get started with Contracts as proposed for C++26 in P2900.

Contracts for C++ explained in 5 minutes

by Timur Doumler

From the article:

With P2900, we propose to add contract assertions to the C++ language. This proposal is in the final stages of wording review before being included in the draft Standard for C++26.

It has been suggested by some members of the C++ standard committee that this feature is too large, too complicated, and hard to teach. As it turns out, the opposite is true: contract assertions are actually very simple and can be explained in just five minutes. In this blog post, we will do exactly this!

VS Code with MS C/C++ Extension: A Confusing UI Design Choice -- Giovanni Dicanio

I wanted to use VS Code with the MS C/C++ Extension for some C++ teaching. In the process, I discovered that setting the C++ language standard to build your C++ code is not as easy and intuitive as one would expect. I discussed the details in this article:

VS Code with MS C/C++ Extension: A Confusing UI Design Choice

by Giovanni Dicanio

From the article:

I pressed Ctrl+Shift+P, selected C/C++ Edit Configurations (UI), and in the C/C++ Configurations page, selected c++20 for the C++ standard.

Then I pressed F5 to start a debugging session, preceded by a build process, and saw that the build process failed.

I took a look at the error message in the terminal window, and to my surprise the error messages were telling me that some libraries (like <span>) were available only with C++20 or later. But I had just selected the C++20 standard a few minutes ago!

 

Inside STL: The atomic shared_ptr -- Raymond Chen

RaymondChen_5in-150x150.jpgThe C++20 standard introduced a specialization of std::atomic for shared pointers: std::atomic<shared_ptr<T>>. How does it work?

Inside STL: The atomic shared_ptr

by Raymond Chen

From the article:

Recall that a normal shared_ptr consists of two pointers: A stored pointer that the shared_ptr returns when you call get() and a pointer to a control block which holds the strong reference count, the weak reference count, and a pointer to the managed object.

The atomic version of the shared_ptr has the same layout, with one change: The bottom two bits of the pointer to the control block are used as flags.

Exercise: Why use the control block pointer instead of the stored pointer to store the flags?

Both the glibc++ libstdc++ and msvc implementations use the bottom bit of the control block pointer as a lock bit: Before performing an operation on the atomic shared pointer, the implementation atomically sets the lock bit to indicate that an atomic operation is in progress. If anybody tries to set the lock bit and finds that it’s already set, they wait for bit to clear. When the owner of the lock bit completes the atomic operation, it clears the lock bit, allowing any waiting threads to proceed.

The difference between libstdc++ and msvc is how they wait for the lock bit to clear.

How frivolous use of polymorphic allocators can imbitter your life

Do you want to stay ahead of the curve and start to use polymorphic allocators in your projects? Are you undeterred even by the cost of virtual calls? If so, it's time to talk about the nuances with a lifetime and why you can't just replace containers with analogs from the 'pmr' namespace.

How frivolous use of polymorphic allocators can imbitter your life

by Grigory Semenchev

From the article:

The developers' prayers have been answered! Starting with C++17, you can use polymorphic allocators. Their idea is a little different from what we need. What is important is that they allow you to specify a buffer from which the allocator will take memory. Such a buffer is called a resource, and it must be inherited from std::memory_resource. It's also important that C++17 introduced several standard resources. Let's examine std::unsynchronized_pool_resource as an example. I should admit that all options mentioned in this article mostly apply to all standard library resources.

C++26: Delete with a Reason -- Sandor Dargo

SANDOR_DARGO_ROUND.JPGLet’s start exploring C++26 with a simple but useful change. Thanks to Yihe Li’s proposal (2573R2), when we =delete a special member function or a function overload, we can specify a reason.

C++26: Delete with a Reason

by Sandor Dargo

From the article:

This is a practical and not very surprising change. Why do I say it’s not very surprising? Adding the ability to specify reasons for some operations has become a pattern in C++ evolution. Since C++11, we can add an optional message to static_assert, C++14 enriched the [[deprecated]] attribute with an optional reason, and the same happened in C++20 to the [[nodiscard]] attribute.

The reason is always similar, if not the same, to enhance maintainability and readability. When it comes to readability, not only the code but also the diagnostic messages become easier to grasp. Understanding why the compiler emitted a warning or an error becomes easier.

This latter is even more important than the readability of the codebase. I mean you could still add a comment right before or after a deleted function, but it wouldn’t be used in the compilers’ messages.

The usage is simple, if you want to specify a reason why a function or function overload is deleted, just pass a string literal containing the reason after delete surrounded by parentheses.

class NonCopyable
{
public:
    // ...
    NonCopyable() = default;

    // copy members
    NonCopyable(const NonCopyable&)
        = delete("Since this class manages unique resources, copy is not supported; use move instead.");
    NonCopyable& operator=(const NonCopyable&)
        = delete("Since this class manages unique resources, copy is not supported; use move instead.");
    
    // provide move members instead
    // ... 
};

When a default-initializable type actually isn't -- Kaashif Hymabaccus

Depositphotos_170038592_S.jpgThe C++ proposal for indirect and polymorphic introduces two new class templates designed to simplify working with dynamically allocated types while retaining value semantics. This post dives into a curious case with polymorphic, exploring why std::default_initializable<polymorphic<T>> evaluates to true—even when polymorphic<T> can't actually be default-initialized in practice.

When a default-initializable type actually isn't

by Kaashif Hymabaccus

From the article:

I was looking at a proposal for adding value-semantic dynamically-allocated types to C++. You can find it here. This proposal adds two class templates, indirect and polymorphic.

The primary use case for this is to make it easier to write correct composite classes. A motivating example can be found through existential types.

Suppose you want a type T which owns (ownership is key) some objects implementing some interfaces. You don't know what concrete types the sub-objects have, and you don't care. You're fine with dynamic dispatch, with the overhead that entails at runtime. You want value semantics, meaning (among other things) copying T copies the sub-objects too.

In Rust, this is expressible through Box<dyn T>, which lets us own objects and perform dynamic dispatch with value semantics. This is what polymorphic will allow in C++, allowing you to avoid hacking around unique_ptr. See the proposal above for more detailed motivation.

 

Understanding and Improving Clang -ftime-report -- Fangrui Song

Clang provides a few options to generate timing report. Among them, -ftime-report and -ftime-trace can be used to analyze the performance of Clang's internal passes. This post focuses on the traditional -ftime-report, which uses a line-based textual format.

Understanding and Improving Clang -ftime-report

by Fangrui Song

From the article:

The output consists of information about multiple timer groups. The last group spans the largest interval and encompasses timing data from other groups.

Up to Clang 19, the last group is called "Clang front-end time report". You would see something like the following.

clang-song.png

The "Clang front-end timer" timer measured the time spent in clang::FrontendAction::Execute, which includes lexing, parsing, semantic analysis, LLVM IR generation, optimization, and machine code generation. However, "Code Generation Time" and "LLVM IR Generation Time" belonged to the default timer group "Miscellaneous Ungrouped Timers". This caused confusion for many users. For example, https://aras-p.info/blog/2019/01/12/Investigating-compile-times-and-Clang-ftime-report/ elaborates on the issues.