Designing Traits and Policy Classes

Traits and policy classes are often used with C++ generics, but their role and purpose is often something of an enigma even to experienced C++ programmers. The definitions of these two terms overlap to some extent, and could be summarized as follows:

  • Traits represent natural additional properties of a template parameter.
  • Policies represent configurable behavior for generic functions and types.

In this article the example code will show use of both of these two, with type information obtained through a (specialized) traits class and functionality obtained from a (generic) policy class.

Continue reading “Designing Traits and Policy Classes”

Applying Functional Programming Techniques to Modern C++

Functional programming (FP) is a discipline and practice of computer science where Mathematical concepts come to the fore. There are a number of popular FP languages out there, but we can stay with C++ and explore some of the themes of FP by using a subset of familiar syntax. In this article we’ll look at a number of FP concepts, such as purity, immutability and use of higher-order functions, and how they can be concisely and usefully represented in Modern C++.

1. Purity

A function is considered pure if its operation depends only upon its formal input parameters, that is not accessing any external (global) state. Global state in FP is a little like the historical Goto statement, shunned but sometimes necessary, and so is by design abstracted away as much as possible. A C++ lambda is pure if it has an empty capture clause, for example:

Continue reading “Applying Functional Programming Techniques to Modern C++”

Designing Classes for Serialization (4)

In the previous articles of this mini-series we’ve covered the use of custom serialization and deserialization functions to generate and interpret XML. In this article we’ll look at how to add to existing classes to give them the ability to utilize the (de-)serialization logic already written. The process is similar to before: create an in-memory model and then serialize it, or start with blank containers and then read in the data, checking for errors.

Continue reading “Designing Classes for Serialization (4)”

Designing Classes for Serialization (3)

In the previous articles we’ve looked at creating an in-memory XML hierarchy (or DOM), and serializing from and deserializing to this memory model. In this article we’re going to look at querying the DOM in a similar fashion to JavaScript methods such as document.getElementById() available in a browser. The scheme chosen is to overload operator [] (twice) and provide other convenience methods such as name() and numberOfChildren().

Continue reading “Designing Classes for Serialization (3)”

Designing Classes for Serialization (2)

The complement of serialization is deserialization, and this is typically more difficult as it requires character- or pattern-matching of the input, plus checking for erroneous input. To match a stream of XML the possibility of using std::getline() was considered, but this is too inflexible as regards whitespace. Stream input to a std::string was also considered, but again this is unsuitable as breaking all input at whitespace is not what is needed.

Continue reading “Designing Classes for Serialization (2)”

Designing Classes for Serialization (1)

Data held in memory must be saved to a store in order to outlive the running-time of the program it belongs to. Simply dumping binary data to disk is not usually the best way, or even a practicable way, of achieving this (think security issues, endianness, 32-bits/64-bits etc.)

The terms “serialization” and its companion “deserialization” are used to describe the conversion between the in-memory model and a (usually textual) disk-file representation. As an example, consider a web-browser which reads an HTML web page (and its dependencies) from a network connection and converts (deserializes) it into a format which can be manipulated through the DOM (Document Object Model). In this article we’ll concentrate more on serialization, which is often a simpler task.

Continue reading “Designing Classes for Serialization (1)”

Common mistakes to avoid in Modern C++ (1)

Learning a new programming language is hard, and is especially daunting when as a novice programmer the compiler rejects pretty much every program you write the first time you try to compile it. Of course, compiler errors and warnings are important as they encourage you to write correct code and ensure that your program actually runs at all, and works as expected.

C++ has traditionally been seen as one of the harder programming languages for beginners to pick up; ideally you should already have some coding experience under your belt in (an)other programming language(s) before trying to learn Modern C++. This mini-series intends to examine the parts of C++ that novice (and more experienced) programmers sometimes fail to understand fully, leading to buggy and/or sub-optimal code.

Continue reading “Common mistakes to avoid in Modern C++ (1)”

Generic classes in Modern C++

In this article we’re going to continue the theme of a class-designer’s toolkit, looking at adding generics (template functionality) to C++ classes. Templates have been around since C++98, and almost all C++ programmers will have used them: std::vector<int> has the type int as a parameter, itself being a specialization of a generic class. Any user-defined type can be used as a type parameter, having equal status to the built-in types.

Generic classes

Classes which are preceded by a the template keyword are automatically turned into generic classes. These classes can have any number of template parameters, we’re going to concentrate on classes having just one, this being a template type parameter. The class definition starts of as follows:

Continue reading “Generic classes in Modern C++”

A Modern C++ class designer’s toolkit

C++ has promoted class design throughout its history, and Modern C++ continues this tradition. Some new syntax has been added, while other syntax is used less often, or has been deprecated. This article aims to summarize best practice using the latest versions of the language in one place, preferring to outline the modern variants (only) without reference to historical style.

Continue reading “A Modern C++ class designer’s toolkit”

Applications of C++23’s deducing ‘this’

All C++ programmers should understand the concept of “const-correctness” which is an additional form of type safety provided by the language. (C99 even incorporated this keyword and feature after C++ introduced it.) A common example of this feature is where classes provide accessors (getters/setters) to member data, with const member functions for the case where member data is logically immutable. A non-const-correct Matrix class allowing element access might look as follows:

Continue reading “Applications of C++23’s deducing ‘this’”

Visitor Pattern in Modern C++

The Visitor Pattern is a well-known technique of adding specific functionality to a number of possibly unrelated classes without actually modifying them significantly. If you do an online search for examples of this design pattern in C++, you may find examples with an abstract Visitor base class having a single, overloaded, pure virtual function, often called accept(). This article explores how to accomplish much the same task using compile-time polymorphism and more recent C++ syntax.

Continue reading “Visitor Pattern in Modern C++”

Know ‘constexpr’? Here’s ‘consteval’, ‘constinit’

As you may know, and as described in Chapter 4 of the Guide on this site, functions (and variables) may be declared constexpr in Modern C++. Functions declared with this keyword are guaranteed to be able to be called at compile-time, returning a result which can be used where a compile-time constant is needed. Importantly, these functions can also be called at with run-time-defined parameters, with the result of the function calculated at run-time with the same logic.

The new keyword consteval, added in C++20, can be used with function definitions to ensure that evaluation is performed at compile-time only. The restrictions are similar to those for constexpr functions (global state cannot be modified) with the added restriction that only constant parameter values are passed to the function when it is called. The following function definition is a valid consteval function:

Continue reading “Know ‘constexpr’? Here’s ‘consteval’, ‘constinit’”

C++ Iterators Primer

The C++ “Standard Containers” are meant to be accessed through iterators, which are described in the course on this site as pointer-like objects which yield an element when dereferenced. Of course, programmers coming from other language backgrounds sometimes to prefer to use indexing, at least at first, however not all container types offer a subscript operator due to implementation issues (std::list does not, for example).

The Standard Containers have always provided member functions to provide first and one-past-last elements, however since C++11 non-member functions are also available within the std namespace, and it is these which allow the functionality for range-for loops, also since C++11. The full list of functions is summarized below:

Continue reading “C++ Iterators Primer”