In C++, How Can I Make a Default Parameter be the This Pointer of the Caller? -- Raymond Chen

RaymondChen_5in-150x150.jpgIn C++, associating member objects like properties or events with their containing class often requires passing this redundantly. This article explores a generalized, flexible solution using templates, variadic arguments, and deducing this to streamline ownership initialization without boilerplate.

In C++, How Can I Make a Default Parameter be the This Pointer of the Caller? Revisited

by Raymond Chen

From the article:

Some time ago, we looked at making the default parameter of a method be the this pointer of the caller. The scenario was something like this:

struct Property
{
    Property(char const* name, int initial, Object* owner) :
        m_name(name), m_value(initial), m_owner(owner) {}

    ⟦ other methods elided - use your imagination ⟧

    char const* m_name;
    Object* m_owner;
    int m_value;
};

struct Widget : Object
{
    Property Height{ "Height", 10, this };
    Property Width{ "Width", 10, this };
};

and we didn’t want to have to type this as the last parameter to all the Property constructors. We came up with this:

template<typename D>
struct PropertyHelper
{
    Property Prop(char const* name, int initial)
    { return Property(name, initial, static_cast<D*>(this)); }
};

struct Widget : Object, PropertyHelper<Widget>
{
    Property Height = Prop("Height", 10);
    Property Width = Prop("Width", 10);
};

The Operations for Reading and Writing Single Elements for C++ Standard Library Maps -- Raymond Chen

RaymondChen_5in-150x150.jpgSome time ago, I noted that the std::map subscript operator is an attractive nuisance. It is the most convenient syntax, but is not often what you actually want.

The Operations for Reading and Writing Single Elements for C++ Standard Library Maps

by Raymond Chen

From the article:

I’ve broken down the various std::map lookup and update operations into a table so you can choose the best one for your situation.
2024-11-21_13-35-17.png

In the table above, key is the map key, value is the mapped type, and params are parameters to the mapped type constructor.

Note that insert and the first emplace¹ take a value which is discarded if it turns out that the key already exists. This is undesirable if creating the value is expensive.

One frustrating scenario is the case where the mapped type’s default constructor is not the constructor you want to use for operator[], or if you want the initial mapped value to be the result of a function call rather than a constructor. Here’s something I sort of threw together.

C++ Online 2025 Registration now Open

C++ Online conference and workshop tickets are now available:

C++ Online 2025 Registration Now Open!

by C++ Online

From the article:

We’re excited to announce that ticket sales for C++Online 2025 are officially open! Join us from 26th - 28th February for three days packed with expert talks, networking, and interactive virtual experiences—all from the comfort of your own home.

Trip Report: Fall ISO C++ Meeting in Wrocław, Poland -- Jonathan Müller

Depositphotos_170038592_S.jpgJonathan Müller attended the fall 2024 meeting of the ISO C++ standardization committee in Wrocław, Poland. This was the fifth meeting for the upcoming C++26 standard and the feature freeze for major C++26 features.

Trip Report: Fall ISO C++ Meeting in Wrocław, Poland

by Jonathan Müller

From the article:

For an overview of all the papers that made progress, read Herb Sutter's trip reportContracts and profiles are the big ticket items that made the most progress this meeting. Contracts is forwarded to wording review, while still being fiercely opposed by some. Profiles is essentially standardized static analysis to improve memory safety, although some deem it ineffective. Due to various scheduling conflicts I did not attend any of the relevant discussions in these spaces. Instead, I am going to share my thoughts about ranges, relocation, and reflection.

Ranges

I've spent the first day and a half co-chairing SG 9, the study group for std::ranges. During discussions, we realized two big holes in the range library that we need to address as soon as possible. They both concern the concept of sized ranges.

The first hole is related to proposal P3179—C++ parallel range algorithms, which adds an execution policy to the algorithms in std::ranges. This makes it trivial to run multi-threaded algorithms: Instead of writing std::ranges::transform(vec, output, fn), you write std::ranges::transform(std::execution::par, vec, output, fn) and now your input is split into multiple chunks and processed in parallel.

PVS-Studio 7.34: support for Apple Silicon ARM64, CodeChecker

PVS-Studio 7.34 has been released. Discover the latest features, including support for Apple Silicon processors with ARM64 architecture, .NET 9 project compatibility, the introduction of the taint analysis mechanism in the Java analyzer, and more.

PVS-Studio 7.34: support for Apple Silicon ARM64, CodeChecker

by Aleksandra Uvarova

From the article:

New diagnostic rules. C, C++:

  • V1116. Creating an exception object without an explanatory message may result in insufficient logging.
  • V1117. The declared function type is cv-qualified. The behavior when using this type is undefined.
  • V2022. Implicit type conversion from integer type to enum type.
  • V5014. OWASP. Cryptographic function is deprecated. Its use can lead to security issues. Consider switching to an equivalent newer function.

 

C++ programmer's guide to undefined behavior: part 11 of 11

Your attention is invited to the 11th part of an e-book on undefined behavior. This is not a textbook, as it's intended for those who are already familiar with C++ programming. It's a kind of C++ programmer's guide to undefined behavior and to its most secret and exotic corners. The book was written by Dmitry Sviridkin and edited by Andrey Karpov.

C++ programmer's guide to undefined behavior: part 11 of 11

by Dmitry Sviridkin

From the article:

Developing multithreaded applications is always challenging. The problem of synchronizing access to shared data is a perennial headache. It'd be ideal if we had a well-tested, reliable library of containers, high-level primitives, and parallel algorithms that managed all invariants. It'd be ideal if static compiler checks prevented us from misusing all these things. How nice it would be... Before C++11 and the standardized memory model, we could use threads but only at our risk. Starting with C++11, there are some pretty low-level primitives in the standard library. Since C++17, there are still various parallel versions of algorithms, but we can't even fine-tune the number of threads or their priorities.

The Puzzle of Trying to Put an Object into a std::optional -- Raymond Chen

RaymondChen_5in-150x150.jpgThe std::optional<T> is a powerful tool for handling optional values, but assigning non-trivial types like Doodad to it can lead to unexpected compilation errors. This post explores why such assignments fail and unpacks the nuances of std::optional and type construction in modern C++.

The Puzzle of Trying to Put an Object into a std::optional

by Raymond Chen

From the article:

The C++ standard library template type std::optional<T> has one of two states. It could be empty (not contain anything), or it could contain a T.

Suppose you start with an empty std::optional<T>. How do you put a T into it?

One of my colleagues tried to do it in what seemed to be the most natural way: Use the assignment operator.

struct Doodad
{
    Doodad();
    ~Doodad();
    std::unique_ptr<DoodadStuff> m_stuff;
};

struct Widget
{
    std::optional<Doodad> m_doodad;

    Widget()
    {
        if (doodads_enabled()) {
            // I guess we need a Doodad too.
            Doodad d;
            m_doodad = d;
        }
    }
};

Unfortunately, the assignment failed to compile:

Implicit String Conversions to Booleans -- Sandor Dargo

SANDOR_DARGO_ROUND.JPGIn this article, we'll learn about -Wstring-conversion, something I learned from C++ Brain Teasers by Anders Schau Knatten](https://www.sandordargo.com/blog/2024/10/16/cpp-brain-teasers). Clang offers this compiler warning which fires on implicit conversions from C-strings to bools.

Implicit String Conversions to Booleans

by Sandor Dargo

From the article:

Let’s start with the first part by explaining why such an implicit conversion is possible. A string literal is an array of const chars. Arrays can be converted into pointers, something we talked about last week when we discussed why spans are so useful. This is also called decay. Furthermore, pointers can be converted into booleans. That is how a string literal can be converted into a bool.

static_assert(!!"" == true);
static_assert(static_cast<bool>("") == true);

What might be surprising though is that even an empty string literal is converted into true. The reason is that only a nullptr would be converted into false, but an empty string literal is an array of a size of one so it’s not a nullptr. As a result, "" converted to true. The possible confusion is that the one character in that array of one is the \0 terminator. But this shouldn’t really matter. You shouldn’t use such shady implicit conversions.

We could end this article right here. But life is not ideal and I tried to turn on -Wstring-conversion in a production codebase where I found a few different cases of string literals conversions.

Around the World in C++: Exploring Time Zones with std::chrono -- Bartlomiej Filipek

2024-11-21_12-55-09.pngWhile most time zones use simple hour offsets from UTC, some regions have chosen unusual time differences. In this blog post, we’ll explore how we can discover such zones using C++20’s chrono library.

Around the World in C++: Exploring Time Zones with std::chrono

by Bartlomiej Filipek

From the article:

We’ll use GCC 14.2 as it fully supports C++20 chrono and also std::print from C++23.

First Attempt: Basic Zone Iteration

C++20 introduced comprehensive time zone support through the <chrono> library. The implementation relies on the IANA Time Zone Database (also known as the “tz database” or “zoneinfo”), which is the de facto standard for time zone information used by most operating systems and programming languages.

The Time Zone Database

In C++20, the time zone database is represented by the tzdb class:

2024-11-21_12-57-47.png

Use std::span Instead of C-style Arrays -- Sandor Dargo

SANDOR_DARGO_ROUND.JPGC-style arrays are still used, mostly when you have to deal with C-libraries. They come with significant limitations, particularly when passed to functions where array decay occurs, leading to the loss of size information.

Use std::span Instead of C-style Arrays

by Sandor Dargo

From the article:

While reading the awesome book C++ Brain Teasers by Anders Schau Knatten, I realized it might be worth writing about spans.

std::span is a class template that was added to the standard library in C++20 and you’ll find it in the <span> header. A span is a non-owning object that refers to a contiguous sequence of objects with the first sequence element at position zero.

In its goal, a span is quite similar to a string_view. While a string_view is a non-owning view of string-like objects, a span is also a non-owning view for array-like objects where the stored elements occupy contiguous places in memory.

While it’s possible to use spans with vectors and arrays, most frequently it will be used with C-style arrays because a span gives you safe access to its elements and also to the size of the view, something that you don’t get with C-style arrays.

When and why does it come in handy?