Articles & Books

Inside STL: The string -- Raymond Chen

Raymond ChenYou might think that a std::string (and all of its friends in the std::basic_string family) are basically a vector of characters internally. But strings are organized differently due to specific optimizations permitted for strings but not for vectors.

Inside STL: The string

By Raymond Chen

From the article:

The starting point for a std::basic_string is this:¹

template<typename T>
struct basic_string
{
    T* ptr;
    size_t size;
    size_t capacity;
};

The ptr is a pointer to the beginning of the string contents.

The size is the number of characters in the string, not including the null terminator.

The capacity is the string capacity, not including the null terminator.

The picture for this simplified version is as follows:

string-chen.png

Inside STL: The vector -- Raymond Chen

RaymondChen_5in-150x150.jpgThe C++ language comes with a standard library, and although implementations are welcome to implement the library types in whatever manner they choose, they are constraints imposed by the standard which often force one of a small number of possible implementations.

Inside STL: The vector

By Raymond Chen

The std::vector is one of those types which is constrained to the point that there’s really only one viable implementation.

Internally, a std::vector basically looks like this:

template<typename T>
struct vector
{
    T* first;
    T* last;
    T* end;
};

The first is a pointer to the beginning of a single memory allocation that holds the vector contents.

The last is a pointer one past the end of the last valid vector element.

The end is a pointer one past the end of the last allocated memory for the vector.

The picture for this is as follows:

insidestlpic-chen.png

Inside STL: The Pair and The Compressed Pair -- Raymond Chen

RaymondChen_5in-150x150.jpgThe C++ language comes with a standard library. When you’re debugging your C++ code, you may have to go digging inside the implementation to extract information from crash dumps. This mini-series is going to look at how various C++ standard library types are implemented by the three major implementations (clang, gcc, and msvc).

Inside STL: The Pair and The Compressed Pair

By Raymond Chen

From the article:

The C++ language comes with a standard library. When you’re debugging your C++ code, you may have to go digging inside the implementation to extract information from crash dumps. This mini-series is going to look at how various C++ standard library types are implemented by the three major implementations (clang, gcc, and msvc).

We’ll start with the lowly std::pair. Its definition is quite simple.

template<typename T1, typename T2>
struct pair
{
    T1 first;
    T2 second;
};

The names of the members of std::pair are required by the C++ language standard, so you don’t see any variation here. Here’s how it looks in the Windows debugger:

0:000> ?? t
struct std::pair<int,int>
   +0x000 first            : 0n42
   +0x004 second           : 0n99

Understanding Ranges Views and View Adaptors Objects in C++20/C++23 -- Bartlomiej Filipek

rangesviews-filipek.pngIn this article, we’d shed some light on the implementation of ranges::reverse_view and std::views::reverse. We’ll compare them to understand the differences between views and their adaptor objects.

Understanding Ranges Views and View Adaptors Objects in C++20/C++23

By Bartlomiej Filipek

From the article:

Let’s look at an example to understand how these views work. Assume we have a range r of integers from 1 to 5. When we apply std::views::reverse to r, it creates a view representing the elements of r in the reverse order.
#include <ranges> 
#include <vector> 
#include <iostream>  

int main() {
  std::vector<int> r = {1, 2, 3, 4, 5};  
  auto reversed = r | std::views::reverse;  
  for (auto i : reversed)  
     std::cout << i << " ";   

  // same as:  
  for (auto i : r | std::views::reverse)  
     std::cout << i << " "; 
}

Perfect Forwarding Forwards Objects Not Braced Things Trying To Become Objects -- Raymond Chen

RaymondChen_5in-150x150.jpgIn C++, perfect forwarding is the act of passing a function’s parameters to another function while preserving its reference category. It is commonly used by wrapper methods that want to pass their parameters through to another function, often a constructor.

Perfect Forwarding Forwards Objects, Not Braced Things That Are Trying To Become Objects

By Raymond Chen

From the article:

In C++, perfect forwarding is the act of passing a function’s parameters to another function while preserving its reference category. It is commonly used by wrapper methods that want to pass their parameters through to another function, often a constructor.

template<typename T, typename... Args>
std::unique_ptr<T> make_unique(Args&&... args)
{
    return std::unique_ptr<T>(
        new T(std::forward<Args>(args)...));
}

The make_unique function takes its parameters, forwards them to the T constructor, and then puts the pointer to the newly-constructed T inside a unique_ptr. Those parameters are forwarded perfectly into the constructor: If the original parameters were rvalue reference, then the constructor receives rvalue reference. If the original parameters were lvalue references, then the constructor receives lvalue reference.

But the catch is that it can forward only objects. It can’t forward “braced things that are trying to become objects”.

C++ exceptions and memory allocation failure -- Wu Yongwei

C++ exceptions are habitually disabled in many software projects. A related issue is that these projects also encourage the use of new (nothrow) for fear of exceptions. Is it good practice or bad practice? Also, how likely are we to really encounter out-of-memory errors? I will investigate on this topic and discuss strategies to deal with memory issues.

C++ Exceptions and Memory Allocation Failure

By Wu Yongwei

From the article:

In fact, every time we initialize or modify a string, vector, or map, we may be allocating memory on the heap. If we think that new will end in an exception (and therefore choose to use new (nothrow)), exceptions may also occur when using these mechanisms. In a program that has disabled exceptions, the result will inevitably be a program crash.

Ignoring abnormal scenarios like allocating more memory than the physical memory size at a time (which would likely be a logic error in the program), can a reasonable program still experience memory allocation failures?

C++23: static operator() and static operator[] -- Sandor Dargo

sandordargo.jpgIn this article, we are going to review two new features of C++23. Now the language allows the call operator (operator()) and the subscription operator (operator[]) to be static.

C++23: static operator() and static operator[]

By Sandor Dargo

From the article:

static operator()

As we saw earlier in our big C++ algorithms tutorial, function objects are extensively used in the standard library to customise the behaviour of several functions. With the introduction of ranges in C++20 (and of earlier non-standard libraries), the usage of function objects became even more widespread.

Many function objects are extremely simple. Let’s take an implementation of isEven.

auto isEven = [](int i) {return i % 2 == 0;};

2023-08 Mailing Available

The 2023-08 mailing of new standards papers is now available.

 

WG21 Number Title Author Document Date Mailing Date Previous Version Subgroup
N4956 Concurrency TS2 PDTS Michael Wong 2023-08-15 2023-08   All of WG21
N4958 Working Draft, Programming Languages -- C++ Thomas Köppe 2023-08-14 2023-08   All of WG21
N4959 Editors' Report, Programming Languages -- C++ Thomas Köppe 2023-08-14 2023-08   All of WG21
N4960 Business Plan and Convener's Report: ISO/IEC JTC1/SC22/WG21 (C++) Herb Sutter 2023-08-09 2023-08   All of WG21
P0124R7 Linux-Kernel Memory Model Paul E. McKenney 2023-08-22 2023-08 P0124R6 SG1 Concurrency and Parallelism,SG5 Transactional Memory,SG14 Low Latency
P0124R8 Linux-Kernel Memory Model Paul E. McKenney 2023-08-22 2023-08 P0124R7 SG1 Concurrency and Parallelism,SG5 Transactional Memory,SG14 Low Latency
P0963R1 Structured binding declaration as a condition Zhihao Yuan 2023-08-14 2023-08 P0963R0 EWG Evolution
P1068R8 Vector API for random number generation Ilya Burylov 2023-08-08 2023-08 P1068R7 LEWG Library Evolution
P1967R11 #embed - a simple, scannable preprocessor-based resource acquisition method JeanHeyd Meneide 2023-08-21 2023-08 P1967R10 CWG Core
P2407R5 Freestanding Library: Partial Classes Ben Craig 2023-07-26 2023-08 P2407R4 LWG Library
P2521R5 Contract support -- Record of SG21 consensus Andrzej Krzemieński 2023-08-15 2023-08 P2521R4 SG21 Contracts
P2728R6 Unicode in the Library, Part 1: UTF Transcoding Zach Laine 2023-08-14 2023-08 P2728R5 SG16 Unicode,LEWG Library Evolution
P2746R3 Deprecate and Replace Fenv Rounding Modes Hans Boehm 2023-08-14 2023-08 P2746R2 SG6 Numerics,LEWG Library Evolution
P2795R3 Erroneous behaviour for uninitialized reads Thomas Köppe 2023-07-28 2023-08 P2795R2 SG12 Undefined and Unspecified Behavior,SG23 Safety and Security,EWG Evolution,CWG Core
P2821R4 span.at() Jarrad J. Waterloo 2023-07-26 2023-08 P2821R3 SG23 Safety and Security,LEWG Library Evolution
P2833R1 Freestanding Library: inout expected span Ben Craig 2023-08-19 2023-08 P2833R0 LEWG Library Evolution
P2845R2 Formatting of std::filesystem::path Victor Zverovich 2023-07-23 2023-08 P2845R1 SG16 Unicode,LEWG Library Evolution
P2863R1 Review Annex D for C++26 Alisdair Meredith 2023-08-16 2023-08 P2863R0 EWG Evolution,LEWG Library Evolution
P2864R1 Remove Deprecated Arithmetic Conversion on Enumerations From C++26 Alisdair Meredith 2023-08-16 2023-08 P2864R0 SG22 Compatability,EWG Evolution
P2865R2 Remove Deprecated Array Comparisons from C++26 Alisdair Meredith 2023-08-16 2023-08 P2865R1 SG22 Compatability,EWG Evolution
P2868R1 Remove Deprecated `std::allocator` Typedef From C++26 Alisdair Meredith 2023-08-15 2023-08 P2868R0 LEWG Library Evolution
P2869R1 Remove Deprecated `shared_ptr` Atomic Access APIs From C++26 Alisdair Meredith 2023-08-16 2023-08 P2869R0 LEWG Library Evolution
P2870R1 Remove `basic_string::reserve()` From C++26 Alisdair Meredith 2023-08-16 2023-08 P2870R0 LEWG Library Evolution
P2871R1 Remove Deprecated Unicode Conversion Facets From C++26 Alisdair Meredith 2023-08-08 2023-08 P2871R0 LEWG Library Evolution
P2875R1 Undeprecate `polymorphic_allocator::destroy` For C++26 Alisdair Meredith 2023-08-15 2023-08 P2875R0 LEWG Library Evolution
P2878R5 Reference checking Jarrad J. Waterloo 2023-08-10 2023-08 P2878R4 SG23 Safety and Security
P2885R1 Requirements for a Contracts syntax Timur Doumler 2023-08-15 2023-08 P2885R0 SG21 Contracts,EWG Evolution
P2890R0 Contracts on lambdas Timur Doumler 2023-08-17 2023-08   SG21 Contracts
P2894R0 Constant evaluation of Contracts Timur Doumler 2023-08-22 2023-08   SG21 Contracts
P2896R0 Outstanding design questions for the Contracts MVP Timur Doumler 2023-08-22 2023-08   SG21 Contracts
P2905R2 Runtime format strings Victor Zverovich 2023-07-23 2023-08 P2905R1 LWG Library
P2909R0 Dude, where's my char? Victor Zverovich 2023-08-13 2023-08   SG16 Unicode,LEWG Library Evolution
P2933R0 std::simd overloads for <bit> header Daniel Towner 2023-08-01 2023-08   SG1 Concurrency and Parallelism,LEWG Library Evolution
P2935R0 An Attribute-Like Syntax for Contracts Joshua Berne 2023-08-15 2023-08   SG21 Contracts
P2944R1 Comparisons for reference_wrapper Barry Revzin 2023-08-17 2023-08 P2944R0 LEWG Library Evolution
P2951R2 Shadowing is good for safety Jarrad J. Waterloo 2023-08-10 2023-08 P2951R1 SG23 Safety and Security
P2952R0 auto& operator=(X&&) = default Arthur O'Dwyer 2023-08-10 2023-08   EWGI SG17: EWG Incubator,EWG Evolution
P2953R0 Forbid defaulting operator=(X&&) && Arthur O'Dwyer 2023-08-10 2023-08   EWGI SG17: EWG Incubator,EWG Evolution
P2954R0 Contracts and virtual functions for the Contracts MVP Ville Voutilainen 2023-08-03 2023-08   SG21 Contracts
P2955R0 Safer Range Access Jarrad J. Waterloo 2023-08-10 2023-08   SG23 Safety and Security
P2956R0 Add saturating library support to std::simd Daniel Towner 2023-08-01 2023-08   SG1 Concurrency and Parallelism,LEWG Library Evolution
P2957R0 Contracts and coroutines Andrzej Krzemieński 2023-08-15 2023-08   SG21 Contracts
P2958R0 typeof and typeof_unqual JeanHeyd Meneide 2023-08-21 2023-08   EWG Evolution
P2960R0 Concurrency TS Editor's report for N4956 Michael Wong 2023-08-16 2023-08   All of WG21

C++23: Syntactic Sugar with Deducing This -- Rainer Grimm

syntacticsugar-grimm.pngThe Curiously Recurring Template Pattern (CRTP) is a heavily used idiom in C++. It is similarly resistant to understanding as the classic design pattern visitor I presented in my last post: “C++23: Deducing This“.  Thanks to deducing this, we can remove the C and R from the abbreviation.

C++23: Syntactic Sugar with Deducing This

By Rainer Grimm

From the article:

CRTP

The acronym CRTP stands for the C++ idiom Curiously Recurring Template Pattern and denotes a technique in C++ in which a class Derived is derived from a class template Base. The critical point is that Base has Derived as a template argument.

template <typename T>
class Base{
    ...
};

class Derived : public Base<Derived>{
    ...
};
CRTP is typically used to implement static polymorphism. Unlike dynamic polymorphism, static polymorphism happens at compile time and does not require an expensive run-time pointer indirection.

Introduction to Programming with C++ For Engineers, Book Review -- Bartlomiej Filipek

introprogramming-book.pngLots of practical examples, general programming, software development techniques, OOP, parallel algorithms, plus C++ to combine it all into working applications. This is a short introduction to the book “Introduction to Programming with C++” by Prof. Boguslaw Cyganek, an excellent book for students who start their journey with system coding.

Introduction to Programming with C++ For Engineers, Book Review

By Bartlomiej Filipek

From the review:

“I have been highly impressed by Introduction to Programming with C++ for Engineers and can’t recommend it enough. With its content designed keeping in mind the author’s own students, the book assumes no prior programming experience, making it an excellent choice for anyone who wishes to learn C++ as their first programming language. […]
The book extends its reach beyond just the programming language, shedding light on aspects such as microprocessor operations, software development processes, UML, and more. Furthermore, the appendices cover essential tools like CMake and Git, making this book a comprehensive guide for anyone delving into C++ programming. The detailed content, careful attention to detail, and clarity in explaining concepts have garnered much praise for the book. This makes it an invaluable resource for those aspiring to learn and understand modern C++ programming."