How could Reflection be applied to Modern C++?

Reflection is commonplace in other contemporary programming languages, but support for it in C++ is virtually non-existent. In this article we’re going to summarize what reflection is and how existing C++ techniques to implement it could potentially be improved in the upcoming C++26 Standard.

Reflection is the ability of a running program to inspect, analyze and modify its own structure at runtime. In C++ we would prefer to focus on compile-time reflection, which would not be expected to incur runtime costs. Existing features which do incur runtime costs already in C++ include RTTI (Run-Time Type Information) and virtual function dispatch, while those which do not include TMP (Template Metaprogramming) and compile-time function invocation.

Continue reading “How could Reflection be applied to Modern C++?”

Pattern Matching is coming to Modern C++

Pattern matching is a commonly used idiom in other contemporary programming languages, such as Rust or Haskell, and is a way to inspect and deconstruct value(s) based on their type(s). Unlike destructuring in C++, which takes a single compound type and extracts the fields as separate variables, pattern matching is a way to deal with conditional logic based upon the type(s) involved. In this article we’ll be taking a look into the future (none of the code featured in this article compiles with trunk Clang or GCC at the time of writing) and consider what implications an adoption of this feature into the Standard might have for Modern C++.

Continue reading “Pattern Matching is coming to Modern C++”

Range-for enhancements in C++23

The latest C++ Standard has been with us for a while now, and in this article we’re going to take a look at a couple of useful enhancements to the range-for syntax we’ve used since C++11. Iterating over the elements in a container is a common idiom in C++, and there are several ways of achieving this (using keyword for or the Standard Library’s std::for_each). The two patterns this article covers are iterating with a numerical index, and outputting with a separator.

Continue reading “Range-for enhancements in C++23”

Understanding Iterator Invalidation

As introduced in the Tutorial on this site, practising correct use of iterators is essential for correct and efficient use of the Standard Containers. This article aims to uncover the details of pitfalls that novice and intermediate C++ programmers may encounter when accessing and modifying elements with iterators. To revisit familiar territory, there are a number of different iterator categories: Forward, bidirectional and random access, together with two variants on forward iterators, these being input iterators and output iterators.

Continue reading “Understanding Iterator Invalidation”

Uses of Parser Generators

We tend to think of parser generators as being used to implement the front-end of a programming language compiler, and having graduated from writing the desk-calculator program this is typically what we use them for. In this article we’ll take a look at another application of parser generators, specifically bisonc++, which is creating visualizations of state-transition diagrams for regular expressions.

Regular expressions (regexes for short) are concise ways of writing string-matching patterns. There are lots of operators for POSIX-compatible regexes, but the basis operators are (in order of precedence highest to lowest) the Kleene-closure (a* for zero or more a‘s), concatenation (ab for a followed by b) and set union (a|b for either a or b) . From these we get the identities a+ = aa* and a? = (a|ε) where epsilon derives the empty string. (Operators + and ? are assumed to have precedence equal to *, and cannot be used in combination with each other.)

Continue reading “Uses of Parser Generators”

Memory Allocation Techniques in Modern C++

C++ has always been regarded as a high-performance programming language, in no small part because its memory handling capabilities are close to the machine hardware. Modern C++ continues this tradition with additional abstractions for memory allocation and access, allowing the Standard Library to provide advanced memory management facilities which are easy to use while still being powerful and performant. This article aims to provide an overview of the ways in which available memory can be allocated and used in Modern C++.

Continue reading “Memory Allocation Techniques in Modern C++”

Using Lambda Functions for Delayed Evaluation

Lambda functions (sometimes called “anonymous functions”) have been a part of C++ for many years now, so usage of them should be well accepted. This mini-article is intended to outline a use case for using lambdas to perform a type of “lazy evaluation”, a term from FP (functional programming) languages. Lazy evaluation is not in fact very different from conventional evaluation, except in that the evaluation is delayed until the result is actually required. We will look at how this can be useful when working with (mutable) independent variables which are able to be changed (something usually not possible with FP).

Continue reading “Using Lambda Functions for Delayed Evaluation”

Exploring C++23’s flat_map

This article intends to examine how to utilize the container adapters std::flat_map and std::flat_set, which are both new to the C++23 Standard Library. You’re probably already familiar with std::map and std::unordered_map (and their “multi” variants), and may be curious as to why we need another associative container type. The reason, as usual for C++, is performance—in some cases, operations on a std::flat_map can outperform those on a std::map or a (sorted) std::vector.

Continue reading “Exploring C++23’s flat_map”

Linear Algebra support in C++26

It’s likely that you’re already familiar with std::string_view and std::span<T> in Modern C++, each of which provides a lightweight “view” onto either string data or other contiguous typed data (such as made available by std::vector<T>::data()). A key difference is that std::string_view is immutable, even if initialized with non-const data. (You could instead use std::span<char> to get around this, if necessary.) A limitation of std::span<T> is that it only supports a single-dimensional view, so is not guaranteed to work with a construct like the following:

void f() {
  int array2d[2][3];
  std::span<int> arr_span{ reinterpret_cast<int*>(array2d), 6 };  
  // ...
}
Continue reading “Linear Algebra support in C++26”

Replacing the Preprocessor in Modern C++

Back in the early days when the original C++ compiler compiled into C, it seemed natural to use the existing C preprocessor to add C (and C++) headers to each source file in order to create a coherent compilation unit. With the Standard Library available as a module in the C++23 standard, it’s time we tried to use other features of Modern C++ to fulfil tasks we’ve previously relied on the C preprocessor for. This article aims to cover all of these main features.

Continue reading “Replacing the Preprocessor in Modern C++”

Selecting Functions at Runtime

Not all choices can be made at compile-time, sometimes including which function (of several possibilities) to invoke. This article aims to cover all of the methods available to Modern C++ when selecting which function to call, with the decision made at runtime (based upon user input, for example). Terms covered in this article include function pointers, function objects, virtual functions and lambdas.

Continue reading “Selecting Functions at Runtime”

Signaling error conditions without exceptions

In this article we’re going to look at a feature new to C++23 which supports a way to return an error condition from a function where a result value was anticipated. This is enabled in a new header <expected> which (as far as I am aware) does not require specific compiler support. (MSVC 19.37 with /std:c++latest was used to test the program code in this article.)

Continue reading “Signaling error conditions without exceptions”

Selecting Functions at Compile Time

When writing C++, we like to do as much of the work as possible at compile time; with C++ being a statically-typed language, we know the type(s) involved when compilation is taking place. In this article we’ll look at how to pass and receive, variables and results, of differing types depending on the nature of the function call itself. The four methods we will examine are: function overloading, template specialization, tag dispatch, and SFINAE.

Continue reading “Selecting Functions at Compile Time”

Concepts 101

Concepts finally appeared in the language with the completion of C++20—I say finally as work to specify them had been going on continuously since before the release of C++11. This article attempts to explain their rationale and usage, with examples that should compile on any up-to-date C++ compiler when specifying -std=c++20 (or /std:c++20 for MSVC).

So why do we need concepts when template syntax has been available since C++98? Put simply, templates have been (successfully) used in ways that were never envisaged; however the reporting of invalid instantiations and similar errors has not kept pace. Also, the use of auto in function parameter lists gives us template syntax “invisibly”, which the novice/intermediate coder may not expect.

Continue reading “Concepts 101”