News

Writing Senders -- Lucian Radu Teodorescu

2025-05-08_16-35-43.pngIn the December issue of Overload [Teodorescu24], we provided a gentle introduction to senders/receivers, arguing that it is easy to write programs with senders/receivers. Then, in the February issue [Teodorescu25a], we had an article that walked the reader through some examples showing how senders/receivers can be used to introduce concurrency in an application. Both of these articles focused on the end users of senders/receivers. This article focuses on the implementer’s side: what does it take to implement senders?

Writing Senders

by Lucian Radu Teodorescu

From the article:

If people are just using frameworks based on std::execution, they mainly need to care about senders and schedulers. These are user-facing concepts. However, if people want to implement sender-ready abstractions, they also need to consider receivers and operation states – these are implementer-side concepts. As this article mainly focuses on the implementation of sender abstractions, we need to discuss these two concepts in more detail.

A receiver is defined in P2300 as “a callback that supports more than one channel” [P2300R10]. The proposal defines a concept for a receiver, unsurprisingly called receiver. To model this concept, a type needs to meet the following conditions:

  • It must be movable and copyable.
  • It must have an inner type alias named receiver_concept that is equal to receiver_t (or a derived type).
  • std::execution::get_env() must be callable on an object of this type (to retrieve the environment of the receiver).

A receiver is the object that receives the sender’s completion signal, i.e., one of set_value()set_error(), or set_stopped(). As explained in the December 2024 issue [Teodorescu24], a sender may have different value completion types and different error completion types. For example, the same sender might sometimes complete with set_value(int, int), sometimes with set_value(double), sometimes with set_error(std::exception_ptr), sometimes with set_error(std::error_code), and sometimes with set_stopped(). This implies that a receiver must also be able to accept multiple types of completion signals.

The need for completion signatures is not directly visible in the receiver concept. There is another concept that the P2300 proposal defines, which includes the completion signatures for a receiver: receiver_of<Completions>. A type models this concept if it also models the receiver concept and provides functions to handle the completions indicated by Completions. More details on how these completions look will be covered in the example sections.

Learn about generic programming and concepts, views & ranges with Nicolai Josuttis

Meeting C++ is hosting two trainings on the 26th and 27th May with Nicolai Josuttis:

May 26th: Generic programming in C++ with templates and auto

Generic code is key for the success of C++. Almost all parts of the C++ standard library are implemented as templates and with auto. However, the uncertainty when seeing this code and when writing own code is high.

This online training will guide you through the most important elements of generic programming for ordinary application programmers. Based on the general approach for function templates and class templates we cover the more tricky topics like non-type template parameters, variadic templates and fold expressions, class template argument deduction, type traits, and SFINAE.

This can be used as perfect base for the training about C++20/C++23 concepts, which are covered in a training the day after.

 

May 27th: Concepts, Ranges, and Views - The New Way of Programming in C++

Concepts, ranges, and views, introduced with C++20 and extended with C++23, introduce a new way of programming with C++:


    Concepts establish a way to deal with requirements and constraints to simplify overloading and improve error messages of generic code. This sounds simple but changes the way we write code significantly.

    Ranges and views establish a new way to deal with collections and containers. Instead of using begin() and end(), we deal with the collections as a whole. This establishes new ways of data processing (such as defining pipelines) but also introduces new pitfalls and caveats.


Both features were designed together so that they benefit from each other:


    Ranges and views are implemented using concepts to behave well and help with their usage.

    As a consequence, standard concepts were designed according to a real non-trivial application of using them.


This full day tutorial guides you though these new features. The features are motivated and explained so that you understand purpose and design as well as how to use them in practice. This also implies to talk about the most important pitfalls (there are several) so that you avoid wasting time or getting even frustrated by unexpected behavior or strange errors.

 

You also can get both as two in one package.

Using Token Sequences to Iterate Ranges -- Barry Revzin

There was a StackOverflow question recently that led me to want to write a new post about Ranges. Specifically, I wanted to write about some situations in which Ranges do more work than it seems like they should have to. And then what we can do to avoid doing that extra work.

Using Token Sequences to Iterate Ranges

by Barry Revzin

From the article:

The Problem

For the purposes of this post, I’m just going to talk about the very simple problem of:

for (auto elem : r) { 
use(elem); 
} 

In the C++ iterator model, this desugars into something like:

auto __it = r.begin(); 
auto __end = r.end(); 

while (__it != __end) { 
use(*__it); 

++__it; 
} 

I used a while loop here deliberately, because it’s a simpler construct and it lets me write the advance step last.

Now, if you want to customize the behavior of a range, those are your entry points right there. You can change what the initialization phase does (begin() and end()), you can change the check against completeness (__it != __end), you can change the read operation (*__it), and you can change the advance operation (++__it). That’s it. You can’t change the structure of the loop itself.

That alone is enough to offer a pretty large wealth of functionality. It’s a very powerful abstraction.

1-day workshop on May 30: Safe and Efficient C++ for Embedded Environments -- Andreas Fertig

me.pngFriday, May 30th, 2025, 10:00 - 18:00 Berlin time (online)

1-day workshop on May 30: Safe and Efficient C++ for Embedded Environments

by Andeas Fertig

About the training

I'm thrilled to let you know that I'll give the workshop "Safe and Efficient C++ for Embedded Environments".

The workshop will take place on Friday, May 30th, 2025, 10:00 - 18:00 Berlin time. It is a remote workshop, so we can join from everywhere.

The course is specifically for people in the embedded domain. You'll learn about various features of modern C++, as you can see in the outline below:

  • Language features in C++
    • References
    • nullptr
    • Explicit data type conversion
    • Uniform initialization
    • Digit separator
    • auto type deduction
    • range-based for loops
    • Strongly typed enum
    • static or inline
    • Attributes
  • ROM-ability
  • Living without the heap
  • Dynamic memory management
  • alignas & alignof
  • Placement-new
  • Implementing a pool allocator
  • std::launder
  • std::unique_ptr
  • std::start_life_time_as

C++ on Sea 2025 Full Schedule, including workshops

C++ on Sea 2025 runs from 23rd-25th June, with workshops on 26th-27th.

The full 2025 schedule is now available

by C++ on Sea

From the article:

This year we are, once again, running 2-day workshops - but they will be after the main conference, at the end of the week. As usual we have a great range of timely topics from world-class instructors to help you keep ahead.

We'll kick off with [a keynote from] Herb Sutter... regroup in the middle with Timur Doumler... then round out with Kristen Shaker.

Lightning talks... conference dinner... and a C++ quiz night.

 

CLion Is Now Free for Non-Commercial Use

Great news for C++ enthusiasts working on personal projects! JetBrains has announced that CLion is now available for free for non-commercial use.

CLion Is Now Free for Non-Commercial Use

by JetBrains

From the article:

"Whether you're a student, an Arduino experimenter, or someone who loves С and C++ with all your heart despite all the challenges these languages present, CLion is now available to you for free – as long as you're not using it for commercial work."

Speeding up C++ Code with Template Lambdas -- Daniel Lemire

image-16-825x510.jpgInteger division is one of the most expensive operations in C++, but when the divisor is known at compile time, the compiler can optimize it significantly. This post explores different approaches—using templates, lambda expressions, and template metaprogramming—to speed up division while maintaining clean and efficient code.

Speeding up C++ Code with Template Lambdas

by Daniel Lemire

From the article:

Let us consider a simple C++ function which divides all values in a range of integers:

void divide(std::span<int> i, int d) {
 for (auto& value : i) {
 value /= d;
 }
}

A division between two integers is one of the most expensive operations you can do over integers: it is much slower than a multiplication which is, in turn, more expensive than an addition. If the divisor d is known at compile-time, this function can be much faster. E.g., if d is 2, the compiler might optimize away the division and use a shift and a few cheap instructions instead. The same is true with all compile-time constant: the compiler can often do better knowing the constant. (See Lemire et al., Integer Division by Constants: Optimal Bounds, 2021)

GCC 15 is now available, with support for more draft C++26 features

gccegg-65.pngGCC 15 is now available!

Here are some highlights from the release notes' C++ section:

  • C++ Modules have been greatly improved.
  • Compilation time speed ups, e.g. by improving hashing of template specializations.

... and more, see the release notes.

C++26: Removing Language Features -- Sandor Dargo

SANDOR_DARGO_ROUND.JPGC++ is often seen as an ever-growing language, with each new standard introducing powerful features while maintaining backward compatibility. However, C++26 takes a step toward simplification by officially removing deprecated features, including implicit arithmetic conversions for enumerations and direct comparisons of C-style arrays, both of which previously led to unintended behavior.

C++26: Removing Language Features

by Sandor Dargo

From the article:

Probably you all heard that C++ is an ever-growing language - I wrote so many times as well. Each standard indeed comes with a great bunch of highly-anticipated features. At the same time, due to binary compatibility considerations, very few old features are removed. This has several implications:

  • we have probably more than one way to do something
  • the standard keeps growing

This is true, but let’s not forget that each new standard removes some features. In this post, let’s review what are the language features that are removed in C++26 and in a later post, we’ll have a look at the removed library features.

At this point, it’s worth mentioning that a removal from the language usually happens in two steps. First a feature gets deprecated, meaning that its users would face compiler warnings for using deprecated features. As a next step, which in some cases never comes, the compiler support is finally removed.