C++ in Embedded Systems - Interview with Author Amar Mahmutbegović
This weeks interview with Amar about his book on C++ on embedded systems:
C++ in Embedded Systems Interview with Author Amar Mahmutbegović
by Jens Weller
Watch the video
June 16-21, Sofia, Bulgaria
September 13-19, Aurora, CO, USA
October 25, Pavia, Italy
November 6-8, Berlin, Germany
November 3-8, Kona, HI, USA
By Meeting C++ | Jul 20, 2025 04:43 AM | Tags: meetingcpp intermediate embedded community c++23 c++20 c++17 basics
This weeks interview with Amar about his book on C++ on embedded systems:
C++ in Embedded Systems Interview with Author Amar Mahmutbegović
by Jens Weller
Watch the video
By Blog Staff | Jul 17, 2025 02:47 PM | Tags: None
In C++, the presence of a user-declared (but not explicitly deleted) copy constructor is enough for the type to be considered copy-constructible by traits like
std::is_copy_constructible
. However, whether that constructor is instantiable is a separate matter—if it attempts to call a deleted base copy constructor, you'll still get a compile-time error when you actually try to use it.
Why does C++ think my class is copy-constructible when it can’t be copy-constructed?
by Raymond Chen
From the article:
Consider the following scenario:
template<typename T>
struct Base
{
// Default-constructible
Base() = default;// Not copy-constructible
Base(Base const &) = delete;
};template<typename T>
struct Derived : Base<T>
{
Derived() = default;
Derived(Derived const& d) : Base<T>(d) {}
};// This assertion passes?
static_assert(
std::is_copy_constructible_v<Derived<int>>);
Why does this assertion pass? It is plainly evident that you cannot copy a Derived<int> because doing so will try to copy the Base<int>, which is not copyable.
By Blog Staff | Jul 15, 2025 02:43 PM | Tags: None
While C++ doesn’t have native syntax for returning multiple values like some other languages, modern C++ offers powerful tools to accomplish the same goal. With features like
std::tuple
, structured bindings, std::expected
, and std::optional
, handling multiple return values—and even error codes—has become both clean and expressive.
Returning several values from a function in C++ (C++23 edition)
by Daniel Lemire
From the article:
Many programming languages such as the Go programming language are designed to make it easy to return several values at once from a function. In Go, it is often used to return an optional error code. The C++ programming language does not have a built-in support for returning several values. However, several standard types can serve the same purpose. If you need to return two values, you can use an std::pair instance. If you need to return two or more values, an std::tuple instance will do. With recent C++ standards, it works really well!
Suppose we want to compute a division with a string error message when one is trying to divided by zero:
std::tuple<int,std::string> divide(int a, int b) { if (b == 0) { return {0, "Error: Division by zero"}; } return {a / b, "Success"}; }This approach works nicely. The code is clear and readable.
You might be concerned that we are fixing the type (int). If you want to write one function for all integer types, you can do so with concepts, like so:
By Blog Staff | Jul 11, 2025 02:37 PM | Tags: None
Starting from C++23, standard containers support a new set of constructor overloads. These constructors take a
std::from_range
tag, a range and an optional allocator. These from_range
constructors make it easier to construct containers from ranges, helping make C++ code more concise, more expressive, and less error-prone.
Constructing Containers from Ranges in C++23
by Sandor Dargo
From the article:
I’ve written plenty on this blog about standard algorithms, but far less about ranges. That’s mostly because, although I’ve had production-ready compilers with C++20 ranges since late 2021, the original ranges library lacked a few key capabilities.
The biggest gap was at the end of a pipeline: you could transform data lazily, but you couldn’t drop the result straight into a brand-new container. What you got back was a view; turning that view into, say, a
std::vector
still required the old iterator-pair constructor.C++23 fixes that in two complementary ways:
std::to
(an adaptor that finishes a pipeline by converting to a container), andfrom_range
constructors on every standard container.Today we’ll focus on the second improvement, because it’s the one you can implement in your own types, too.
The
from_range
constructorEvery standard container now supports a new set of constructors that make integration with ranges smoother — the so-called
from_range
constructors.These constructors allow you to build a container directly from a range, rather than from a pair of iterators.
By Blog Staff | Jul 9, 2025 02:34 PM | Tags: None
Time flies—C++ Insights just turned 7! To celebrate, I’ve upgraded the tool to Clang 20, unlocking even more C++23 and C++26 features for you to explore.
C++ Insights now uses Clang 20
by Andreas Fertig
From the article:
size_t
For a long time now, when you used
size_t
orstd::size_t
the resulting transformation kept the name. It did not expand to the underlying machine-specific date type. To be honest, that was more like a happy accident. Clang 20 came with two changes to libc++The first https://github.com/llvm/llvm-project/commit/d6832a611a7c4ec36f08b1cfe9af850dad32da2e modularized
<cstddef>
for better internal structuring, avoiding too much content to be included. This patch was followed by a second one: https://github.com/llvm/llvm-project/commit/5acc4a3dc0e2145d2bfef47f1543bb291c2b866a. This one now made an interesting change.Previously, libc++ defined
std::size_t
as
1using ::size_t _LIBCPP_USING_IF_EXISTS;
As the second patch highlighted, this required including the operating systems
<stddef.h>
. In the spirit of reducing unnecessary includes the line was changed to:
1using size_t = decltype(sizeof(int));
This is an easy C++ solution to get the proper data type for
size_t
. Which is great. Yet, the AST nodes of the two versions look different. Previously, the operating system (macOS in this case) defined in its header:
1typedef unsigned long size_t;
Well, with the new version, the transformation no longer stops at
size_t
but expands it all down tounsigned long
. This probably should have been the case from the beginning, but I liked that tests and transformations did not change across platforms in this specific case. However, there are other instances where the transformation did yield different output on different platforms, so I accept this one.
By Blog Staff | Jul 7, 2025 02:31 PM | Tags: None
Visual Studio 2022 version 17.14 is now generally available! This post summarizes the new features you can find in this release for C++. You can download Visual Studio 2022 from the Visual Studio downloads page or upgrade your existing installation by following the Update Visual Studio Learn page.
What’s New for C++ Developers in Visual Studio 2022 17.14
by Sy Brand
From the article:
We’ve made a myriad of fixes and improvements to the MSVC compiler and standard library. See C++ Language Updates in MSVC in Visual Studio 2022 17.14 for a full list of changes on the compiler side, and the STL Changelog for all the standard library updates.
Compiler
We’ve added support for several C++23 features, which are available under the
/std:c++latest
and/std:c++23preview
flags.You can now omit
auto lambda = [] constexpr { }; //no '()' needed after the capture list()
in some forms of lambdas that previously required them, thanks to P1102R2:
We implemented if consteval
, with which you can run different code depending on whether the statement is executed at compile time or run time. This is useful for cases where your run time version can be heavily optimized with compiler intrinsics or inline assembly that are not available at compile time:
constexpr size_t strlen(char const* s) {
if consteval {
// if executed at compile time, use a constexpr-friendly algorithm
for (const char *p = s; ; ++p) {
if (*p == '\0') {
return static_cast<std::size_t>(p - s);
}
}
} else {
// if executed at run time, use inline assembly
__asm__("SSE 4.2 magic");
}
}
By Blog Staff | Jul 3, 2025 02:29 PM | Tags: None
C++’s undefined behaviour impacts safety. Sandor Dargo explains how and why uninitialised reads will become erroneous behaviour in C++26, rather than being undefined behaviour.
C++26: Erroneous Behaviour
by Sandor Dargo
From the article:
If you pick a random talk at a C++ conference these days, there is a fair chance that the speaker will mention safety at least a couple of times. It’s probably fine like that. The committee and the community must think about improving both the safety situation and the reputation of C++.
If you follow what’s going on in this space, you are probably aware that people have different perspectives on safety. I think almost everybody finds it important, but they would solve the problem in their own way.
A big source of issues is certain manifestations of undefined behaviour. It affects both the safety and the stability of software. I remember that a few years ago when I was working on some services which had to support a 10× growth, one of the important points was to eliminate undefined behaviour as much as possible. One main point for us was to remove uninitialized variables which often lead to crashing services.
Thanks to P2795R5 by Thomas Köppe, uninitialized reads won’t be undefined behaviour anymore – starting from C++26. Instead, they will get a new behaviour called ‘erroneous behaviour’.
The great advantage of erroneous behaviour is that it will work just by recompiling existing code. It will diagnose where you forgot to initialize variables. You don’t have to systematically go through your code and let’s say declare everything as auto to make sure that every variable has an initialized value. Which you probably wouldn’t do anyway.
By Blog Staff | Jul 1, 2025 02:26 PM | Tags: None
Senders/receivers can be used to introduce concurrency. Lucian Radu Teodorescu describes how 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 toreceiver_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()
, orset_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 withset_value(int, int)
, sometimes withset_value(double)
, sometimes withset_error(std::exception_ptr)
, sometimes withset_error(std::error_code)
, and sometimes withset_stopped()
. This implies that a receiver must also be able to accept multiple types of completion signals.
By Blog Staff | Jun 27, 2025 02:07 PM | Tags: None
In recent weeks, we’ve explored language features and library features becoming constexpr
in C++26. Those articles weren’t exhaustive — I deliberately left out one major topic: exceptions.
Starting with C++26, it will become possible to throw exceptions during constant evaluation. This capability is enabled through both language and library changes. Given the significance of this feature, it deserves its own dedicated post.
C++26: constexpr Exceptions
by Sandor Dargo
From the article:
P3068R6: Allowing exception throwing in constant-evaluation
The proposal for static reflection suggested allowing exceptions in constant-evaluated code, and P3068R6 brings that feature to life.
constexpr
exceptions are conceptually similar toconstexpr
allocations. Just as aconstexpr string
can’t escape constant evaluation and reach runtime,constexpr
exceptions also have to remain within compile-time code.Previously, using
throw
in aconstexpr
context caused a compilation error. With C++26, such code can now compile — unless an exception is actually thrown and left uncaught, in which case a compile-time error is still issued. But the error now provides more meaningful diagnostics.
By Blog Staff | Jun 26, 2025 01:28 PM | Tags: None
Registration is now open for CppCon 2025! The conference starts on September 15 and will be held in person in Aurora, CO. To whet your appetite for this year’s conference, we’re posting videos of some of the top-rated talks from last year's conference. Here’s another CppCon talk video we hope you will enjoy – and why not register today for CppCon 2025!
Lightning Talk: The UB Detector: constexpr
by Andreas Fertig
Summary of the talk:
A constexpr function evaluated at compile time is free of any undefined behaviour they say. Do you think that statement is true as well?