February 2024

Parsing Numbers At Compile Time with C++17, C++23, and C++26 -- Bartlomiej Filipek

modern-parsingnum.pngThanks to the powerful constexpr keyword and many enhancements in recent C++ standards, we can now perform a lot of computations at compile time. In this text, we’ll explore several techniques for parsing integers, including the “naive” approach, C++23,from_chars,std::optional, std::expected, and even some upcoming features in C++26.

Parsing Numbers At Compile Time with C++17, C++23, and C++26

by Bartlomiej Filipek

From the article:

Why at compile time?

While it may sound like a theoretical experiment, since C++11 we can shift more and more computations to compile-time. Here are some key areas and examples where constexpr can be beneficial:

Starting easy from C++17 

Starting with C++17, we are now capable of writing complex constexpr functions. However, our ability to do so is still limited by the range of algorithms available in that context. Luckily, with the introduction of string_view in that version of C++, there is no longer any need to work with “raw” const char* buffers.

Class Invariants -- Andrzej Krzemieński

Andrzej-Krzemieński.pngThis article explores the concept of class invariants in C++ and their significance in maintaining code integrity and abstraction. It highlights the difference between struct and class definitions and discusses the role of class invariants in guaranteeing the correctness of class objects. The article also touches upon the trade-offs between strong and weak invariants and provides insights into when to define a new class with proper invariants.

Class Invariants

by Andrzej Krzemieński

From the article:

The primary motivation for defining a class in C++ is to reflect and maintain a class invariant. In this post we will see what class invariants are and how you deal with them. Class invariants are important part of C++, even though there is no “invariant” keyword in C++.

Contrast the following two class definitions:

struct Point
{
  int x;
  int y;
};
class Range
{
  int _min;
  int _max;

public:
  // ...
};

In C++ a struct is practically a class but with a different default member access. The first is an aggregate: it only allows two pieces of data to travel together. If it was not for the nice member names, we might have as well used std::pair<int, int> instead. 

Optimizing the Unoptimizable: A Journey to Faster C++ Compile Times -- Victor Zverovich

zverovich-compiletimes.jpgIn this post, Victor talks about bringing compile times of the {fmt} library on par with the C standard I/O library (stdio).

Optimizing the Unoptimizable: A Journey to Faster C++ Compile Times

by Victor Zverovich

From the article:

First some background: {fmt} is a popular open-source formatting library for C++ that provides a better alternative to C++ iostreams and C stdio. It has already surpassed stdio in many areas:

  • Type safety with compile-time format string checks available by default since C++20 and as an opt in for C++14/17. Runtime format strings are also safe to use in {fmt} which is impossible to achieve in printf.
  • Extensibility: user-defined type can be made formattable and most standard library types such as containers, dates and times are formattable out of the box.
  • Performance: {fmt} is significantly faster than common standard library implementations of printf, in some cases by an order of magnitude (e.g. on floating-point formatting).
  • Portable Unicode support.

However, one area where stdio remained significantly better was compile times. 

Seastar, ScyllaDB, and C++23

Seastar announces that now that C++23 is available, they will support C++23 and C++20 (dropping support for C++17) in accordance with their support policy

Seastar, ScyllaDB, and C++23

By Avi Kivity

From the article:

Seastar is an open-source (Apache 2.0 licensed) C++ framework for I/O intensive asynchronous computing, using the thread-per-core model. Seastar underpins several high- performance distributed systems: ScyllaDB, Redpanda, and Ceph Crimson. Seastar source is available on github. As a C++ framework, Seastar must choose which C++ versions to support. The support policy is last-two-versions. That means that at any given time, the most recently released version as well as the previous one are supported, but earlier versions cannot be expected to work. This policy gives users of the framework three years to upgrade to the next C++ edition while not constraining Seastar to ancient versions of the language.

Now that C++23 has been ratified, Seastar now officially supports C++20 and C++23. The previously supported C++17 is now no longer supported.

The Case of the Vector With an Impossibly Large Size -- Raymond Chen

RaymondChen_5in-150x150.jpgIn this software troubleshooting case, a customer experienced program crashes, and a detailed analysis of the code revealed several issues. The primary problem stemmed from lazy initialization of a widget list, leading to inconsistent vector states and potential crashes. Additionally, a multithreading issue was identified, highlighting the importance of thread-safety mechanisms in code that can be accessed concurrently.

The Case of the Vector With an Impossibly Large Size

by Raymond Chen

From the article:

A customer had a program that crashed with this stack:

contoso!Widget::GetCost
contoso!StandardWidgets::get_TotalCost+0x12f
rpcrt4!Invoke+0x73
rpcrt4!Ndr64StubWorker+0xb9b
rpcrt4!NdrStubCall3+0xd7
combase!CStdStubBuffer_Invoke+0xdb
combase!ObjectMethodExceptionHandlingAction<<lambda_...> >+0x47
combase!DefaultStubInvoke+0x376
combase!ServerCall::ContextInvoke+0x6f3
combase!ComInvokeWithLockAndIPID+0xacb
combase!ThreadInvoke+0x103
rpcrt4!DispatchToStubInCNoAvrf+0x18
rpcrt4!RPC_INTERFACE::DispatchToStubWorker+0x1a9
rpcrt4!RPC_INTERFACE::DispatchToStubWithObject+0x1a7
rpcrt4!LRPC_SCALL::DispatchRequest+0x308
rpcrt4!LRPC_SCALL::HandleRequest+0xdcb
rpcrt4!LRPC_SASSOCIATION::HandleRequest+0x2c3
rpcrt4!LRPC_ADDRESS::HandleRequest+0x183
rpcrt4!LRPC_ADDRESS::ProcessIO+0x939
rpcrt4!LrpcIoComplete+0xff
ntdll!TppAlpcpExecuteCallback+0x14d
ntdll!TppWorkerThread+0x4b4
kernel32!BaseThreadInitThunk+0x18
ntdll!RtlUserThreadStart+0x21

They wondered if some recent change to Windows was the source of the problem, since it didn’t happen as much in earlier versions of Windows.

 

DR20 - The Equality Operator You Are Looking For -- Sandor Dargo

SANDOR_DARGO_ROUND.JPGWe delve into how C++20 introduced changes to object comparisons, leading to unexpected behavior and the need for matching operator!= declarations.

DR20 - The Equality Operator You Are Looking For

by Sandor Dargo

From the article:

When I see DR, I immediately think about Disaster Recovery. That’s due to my first corporate job where I worked as a Database Administrator and we had regular exercises to simulate events when datacenters would be unavailable.

When you see DR in the title of a C++ proposal, it’s not about a disaster, it’s more about a bug. DR stands for defect report. But the paper itself is usually not about reporting that there is a problem - that has been already done -, but more about proposing a solution.

What’s more important is that defect reports are not becoming part of the latest standard, they retrospectively change the one that introduced the defect.

A defect of C++20’s equality operator

P2468R2 is addressing a problem that was introduced by C++20. C++20 brought us the spaceship operator (operator<=>), but it further changed the logic of object comparisons. It changed the meaning of == and != and how overload resolution applies to them.

PVS-Studio 7.29: Boost smart pointers, plugin for Qt Creator on macOS

PVS-Studio 7.29 has been released. Now you can analyze Java projects in a plugin for VS Code, check Boost smart pointers, use the PVS-Studio plugin for Qt Creator 12 on macOS, and that's not all.

PVS-Studio 7.29: Java code check in VS Code, Boost smart pointers, and plugin for Qt Creator on macOS

by Gleb Aslamov

From the article:

The C++ analyzer now supports smart pointers from the Boost library: boost::unique_ptr and boost::shared_ptr. Now the PVS-Studio analyzer is able to detect errors such as null pointer dereferences when these classes are used.