- Table of Contents
- Previous Chapter
- Next Chapter

# Chapter 11: More Operator Overloading

Having covered the overloaded assignment operator in chapter 9, and having shown several examples of other overloaded operators as well (i.e., the insertion and extraction operators in chapters 3 and 6), we now take a look at operator overloading in general.

## 11.1: Overloading `operator[]()'

As our next example of operator overloading, we introduce a class `IntArray` encapsulating an array of `int`s. Indexing the array elements is possible using the standard array index operator `[]`, but additionally checks for array bounds overflow are performed (note, however, that index checking is not normally done by index operators. Since it's good practice to avoid surprises array bound checks should normally not be performed by overloaded index operators). The index operator (`operator[]`) is interesting because it can be used in expressions as both lvalue and as rvalue.

Here is an example illustrating the basic use of the class:

        int main()
        {
            IntArray x{ 20 };               // 20 ints

            for (int idx = 0; idx < 20; ++idx)
                x[idx] = 2 * idx;                   // assign the elements

            for (int idx = 0; idx <= 20; ++idx)     // result: boundary overflow
                cout << "At index " << idx << ": value is " << x[idx] << '\n';
        }

First, the constructor is used to create an object containing 20 `int`s. The elements stored in the object can be assigned or retrieved. The first `for`-loop assigns values to the elements using the index operator, the second `for`-loop retrieves the values but also results in a run-time error once the non-existing value `x[20]` is addressed. The `IntArray` class interface is:

        #include <cstddef>

        class IntArray
        {
            size_t d_size;
            int     *d_data;

             public:
                IntArray(size_t size = 1);
                IntArray(IntArray const &other);
                ~IntArray();
                IntArray &operator=(IntArray const &other);

                                                    // overloaded index operators:
                int &operator[](size_t index);              // first
                int const &operator[](size_t index) const;  // second

                void swap(IntArray &other);         // trivial

            private:
                void boundary(size_t index) const;
                int &operatorIndex(size_t index) const;
        };

This class has the following characteristics:

- One of its constructors has a `size_t` parameter having a default argument value, specifying the number of `int` elements in the object.
- The class internally uses a pointer to reach allocated memory. Hence, the necessary tools are provided: a copy constructor, an overloaded assignment operator and a destructor.
- That there are two overloaded index operators. Why are there two?

  The first overloaded index operator allows us to reach and modify the elements of non-constant `IntArray` objects. This overloaded operator's prototype is a function returning a reference to an `int`, allowing us to use an expression like `x[10]` as rvalue or lvalue.

  With non-const `IntArray` objects `operator[]` can therefore be used to retrieve and to assign values. Therefore, the return value of the non-const `operator[]` member is an `int &`, to allow modification of the elements when used as lvalue, whereas the return value of the const `operator[]` member is preferably an `int const &`, rather than a mere `int`. In this situation we prefer the use of a `const &` return value to allow immediate writing of the return value to, e.g., a binary file, as in:

          void writeValue(Intarray const &iarr, size_t idx)
          {
              cout.write(reinterpret_cast<char const *>(&iarr[idx]));
          }

  This whole scheme fails if there's nothing to assign. Consider the situation where we have an `IntArray const stable(5)`. Such an object is an immutable const object. The compiler detects this and refuses to compile this object definition if only the non-const `operator[]` is available. Hence the second overloaded index operator is added to the class's interface. This second form of the overloaded index operator is automatically used by the compiler with `const` objects. It is used for value retrieval instead of value assignment. That, of course, is precisely what we want when using `const` objects. In this situation members are overloaded only by their `const` attribute. This form of function overloading was introduced earlier in the C++ Annotations (sections 2.5.4 and 7.7).

- As there is only one pointer data member, the destruction of the memory allocated by the object is a simple `delete[] data`.

Now, the implementation of the members (omitting the trivial implementation of `swap`, cf. chapter 9) are:

        #include "intarray.ih"

        IntArray::IntArray(size_t size)
        :
            d_size(size)
        {
            if (d_size < 1)
                throw "IntArray: size of array must be >= 1"s;

            d_data = new int[d_size];
        }

        IntArray::IntArray(IntArray const &other)
        :
            d_size(other.d_size),
            d_data(new int[d_size])
        {
            memcpy(d_data, other.d_data, d_size * sizeof(int));
        }

        IntArray::~IntArray()
        {
            delete[] d_data;
        }

        IntArray &IntArray::operator=(IntArray const &other)
        {
            IntArray tmp(other);
            swap(tmp);
            return *this;
        }

        int &IntArray::operatorIndex(size_t index) const
        {
            boundary(index);
            return d_data[index];
        }

        int &IntArray::operator[](size_t index)
        {
            return operatorIndex(index);
        }

        int const &IntArray::operator[](size_t index) const
        {
            return operatorIndex(index);
        }

        void IntArray::swap(IntArray &other)
        {
            // swaps the d_size and d_data data members
            // of *this and other
        }

        void IntArray::boundary(size_t index) const
        {
            if (index < d_size)
                return;
            ostringstream out;
            out  << "IntArray: boundary overflow, index = " <<
                    index << ", should be < " << d_size << '\n';
            throw out.str();
        }

Note how the `operator[]` members were implemented: as non-const members may call const member functions and as the implementation of the `const` member function is identical to the non-const member function's implementation both `operator[]` members could be defined inline using an auxiliary function `int &operatorIndex(size_t index) const`. A `const` member function may return a non-const reference (or pointer) return value, referring to one of the data members of its object. Of course, this is a potentially dangerous backdoor that may break data hiding. However, the members in the public interface prevent this breach and so the two public `operator[]` members may themselves safely call the same `int &operatorIndex() const` member, that defines a private backdoor.

### 11.1.1: Multi-argument `operator[]()'

Consider a standard two-dimensional array. It has `nRows` rows and `nCols` columns. Such an array is a generalization of a one-dimensional array: each row consists of an array of `nCols` elements. If a type `DoubleArray` is available, defined like the `IntArray` of the previous section, but containing `double` values instead of `int` values, then designing a class `Matrix` could start as follows:

        class Matrix
        {
            size_t d_nRows;
            size_t d_nCols;
            DoubleArray *d_row;

            public:
                Matrix(size_t nRows, size_t nCols);
            ...
        };

and its constructor allocates `nRows DoubleArrays`, each having `nCols` columns, with each `DoubleArray` being initialized to a `nCols` elements, initialized to 0 by the `DoubleArray's` default constructor:

        Matrix::Matrix(size_t nRows, size_t nCols)
        :
            d_nRows(nRows),
            d_nCols(nCols),
            d_row(new DoubleArray[nRows])
        {}

Traditionally accessing elements of a `Matrix` could be realized in three ways (plus optionally corresponding `const` variants):

- A member `double &element(size_t row, size_t col)`, returning the value of element `[row, col]`;
- A member `DoubleArray &row(size_t row)`, returning `row's DoubleArray`;
- A member `DoubleArray &operator[](size_t row)`, also returning `row's DoubleArray`;

The members `element` and `row` work fine, but at the disadvantage that the standard syntax for referring to matrix elements is not used. E.g, to access element `matrix[3, 4]` we would write `matrix.element(3, 4)` or `matrix.row(3)[4]`, whereas the third element requires us to use two index operators: `matrix[3][4]`. Moreover, with the second and third members data hiding of `DoubleArray row` is abandoned if the only reason for these members is to access `Matrix` elements.

`operator[]` The overloaded index operator, however, can also be defined having multiple arguments, allowing the use of the (standard mathematical) syntax `matrix[row, col]` (and in general: the overloaded index operator can also have more arguments, which might come in useful when defining, e.g., arrays of arrays).

Providing `Matrix` with an index operator accepting two arguments is simple: just add a member `double &operator[](size_t row, size_t col)` (and optionally a comparable `const` member) to the class's interface. Its implementation may then directly return the requested array element:

        double &Matrix::operator[](size_t row, size_t col)
        {
            return d_row[row][col];
        }

As an aside: note that this implementation does not check whether the provided indices are valid. Traditionally index operators don't perform such checks, improving the efficiency of programs when it's known that indices cannot be invalid. E.g., to initialize all elements of a `Matrix` with subsequent integral values the following function could be used:

        void init(Matrix &matrix, size_t value)
        {
            for (size_t row = 0; row != matrix.nRows(); ++row)
                for (size_t col = 0; col != matrix.nCols(); ++col)
                    matrix[row, col] = value++;
        }

If, on the other hand, checking the validity of the indices is necessary then a multi-argument `at` member like the following can be defined:

        double &Matrix::at(size_t row, size_t col)
        {
            if (row >= d_nrows or col >= d_nCols)
                throw runtime_error("Matrix::at: invalid indices");
            return d_row[row][col];
        }

## 11.2: Overloading insertion and extraction operators

Classes may be adapted in such a way that their objects may be inserted into and extracted from, respectively, a `std::ostream` and `std::istream`.

The class `std::ostream` defines insertion operators for primitive types, such as `int`, `char *`, etc.. In this section we learn how to extend the existing functionality of classes (in particular `std::istream` and `std::ostream`) in such a way that they can be used also in combination with classes developed much later in history.

In particular we will show how the insertion operator can be overloaded allowing the insertion of any type of object, say `Person` (see chapter 9), into an `ostream`. Having defined such an overloaded operator we're able to use the following code:

        Person kr("Kernighan and Ritchie", "unknown", "unknown");

        cout << "Name, address and phone number of Person kr:\n" << kr << '\n';

The statement `cout` << `kr` uses `operator`<<. This member function has two operands: an `ostream &` and a `Person &`. The required action is defined in an overloaded free function `operator`<< expecting two arguments:

                                    // declared in `person.h'
        std::ostream &operator<<(std::ostream &out, Person const &person);

                                    // defined in some source file
        ostream &operator<<(ostream &out, Person const &person)
        {
            return
                out <<
                    "Name:    " << person.name() << ", "
                    "Address: " << person.address() << ", "
                    "Phone:   " << person.phone();
        }

The free function `operator`<< has the following noteworthy characteristics:

- The function returns a reference to an `ostream` object, to enable `chaining' of the insertion operator.
- The two operands of `operator`<< are passed to the free function as its arguments. In the example, the parameter `out` was initialized by `cout`, the parameter `person` by `kr`.

In order to overload the extraction operator for, e.g., the `Person` class, members are needed modifying the class's private data members. Such modifiers are normally offered by the class interface. For the `Person` class these members could be the following:

        void setName(char const *name);
        void setAddress(char const *address);
        void setPhone(char const *phone);

These members may easily be implemented: the memory pointed to by the corresponding data member must be deleted, and the data member should point to a copy of the text pointed to by the parameter. E.g.,

        void Person::setAddress(char const *address)
        {
            delete[] d_address;
            d_address = strdupnew(address);
        }

A more elaborate function should check the reasonableness of the new address (`address` also shouldn't be a 0-pointer). This however, is not further pursued here. Instead, let's have a look at the final `operator`>>. A simple implementation is:

        istream &operator>>(istream &in, Person &person)
        {
            string name;
            string address;
            string phone;

            if (in >> name >> address >> phone)    // extract three strings
            {
                person.setName(name.c_str());
                person.setAddress(address.c_str());
                person.setPhone(phone.c_str());
            }
            return in;
        }

Note the stepwise approach that is followed here. First, the required information is extracted using available extraction operators. Then, if that succeeds, modifiers are used to modify the data members of the object to be extracted. Finally, the stream object itself is returned as a reference.

## 11.3: Conversion operators

A class may be constructed around a built-in type. E.g., a class `String`, constructed around the `char *` type. Such a class may define all kinds of operations, like assignments. Take a look at the following class interface, designed after the `string` class:

        class String
        {
            char *d_string;

            public:
                String();
                String(char const *arg);
                ~String();
                String(String const &other);
                String &operator=(String const &rvalue);
                String &operator=(char const *rvalue);
        };

Objects of this class can be initialized from a `char const *`, and also from a `String` itself. There is an overloaded assignment operator, allowing the assignment from a `String` object and from a `char const *` (Note that the assignment from a `char const *` also allows the null-pointer. An assignment like `stringObject = 0` is perfectly in order.).

Usually, in classes that are less directly linked to their data than this `String` class, there will be an accessor member function, like a member `char const *String::c_str() const`. However, the need to use this latter member doesn't appeal to our intuition when an array of `String` objects is defined by, e.g., a class `StringArray`. If this latter class provides the `operator[]` to access individual `String` members, it would most likely offer at least the following class interface:

        class StringArray
        {
            String *d_store;
            size_t d_n;

            public:
                StringArray(size_t size);
                StringArray(StringArray const &other);
                StringArray &operator=(StringArray const &rvalue);
                ~StringArray();

                String &operator[](size_t index);
        };

This interface allows us to assign `String` elements to each other:

        StringArray sa{ 10 };

        sa[4] = sa[3];  // String to String assignment

But it is also possible to assign a `char const *` to an element of `sa`:

        sa[3] = "hello world";

Here, the following steps are taken:

- First, `sa[3]` is evaluated. This results in a `String` reference.
- Next, the `String` class is inspected for an overloaded assignment, expecting a `char const *` to its right-hand side. This operator is found, and the string object `sa[3]` receives its new value.

Now we try to do it the other way around: how to access the `char const *` that's stored in `sa[3]`? The following attempt fails:

        char const *cp = sa[3];

It fails since we would need an overloaded assignment operator for the 'class' `char const *`. Unfortunately, there isn't such a class, and therefore we can't build that overloaded assignment operator (see also section 11.15). Furthermore, casting won't work as the compiler doesn't know how to cast a `String` to a `char const *`. How to proceed?

One possibility is to define an accessor member function `c_str()`:

        char const *cp = sa[3].c_str()

This compiles fine but looks clumsy.... A far better approach would be to use a conversion operator.

A conversion operator is a kind of overloaded operator, but this time the overloading is used to cast the object to another type. In class interfaces, the general form of a conversion operator is:

        operator <type>() const;

Conversion operators usually are `const` member functions: they are automatically called when their objects are used as rvalues in expressions having a `type` lvalue. Using a conversion operator a `String` object may be interpreted as a `char const *` rvalue, allowing us to perform the above assignment.

Conversion operators are somewhat dangerous. The conversion is automatically performed by the compiler and unless its use is perfectly transparent it may confuse those who read code in which conversion operators are used. E.g., novice C++ programmers are frequently confused by statements like ``if (cin) ...`'.

As a rule of thumb: classes should define at most one conversion operator. Multiple conversion operators may be defined but frequently result in ambiguous code. E.g., if a class defines `operator bool() const` and `operator int() const` then passing an object of this class to a function expecting a `size_t` argument results in an ambiguity as an `int` and a `bool` may both be used to initialize a `size_t`.

In the current example, the class `String` could define the following conversion operator for `char const *`:

        String::operator char const *() const
        {
            return d_string;
        }

Notes:

- Conversion operators do not define return types. The conversion operator returns a value of the type specified beyond the `operator` keyword.
- In certain situations (e.g., when a `String` argument is passed to a function specifying an ellipsis parameter) the compiler needs a hand to disambiguate our intentions. A `static_cast` solves the problem.
- With template functions conversion operators may not work immediately as expected. For example, when defining a conversion operator `X::operator std::string const() const` then `cout << X()` won't compile. The reason for this is explained in section 21.9, but a shortcut allowing the conversion operator to work is to define the following overloaded `operator<<` function:

      std::ostream &operator<<(std::ostream &out, std::string const &str)
      {
          return out.write(str.data(), str.length());
      }

Conversion operators are also used when objects of classes defining conversion operators are inserted into streams. Realize that the right hand sides of insertion operators are function parameters that are initialized by the operator's right hand side arguments. The rules are simple:

- If a class `X` defining a conversion operator also defines an insertion operator accepting an `X` object the insertion operator is used;
- Otherwise, if the type returned by the conversion operator is insertable then the conversion operator is used;
- Otherwise, a compilation error results. Note that this happens if the type returned by the conversion operator itself defines a conversion operator to a type that may be inserted into a stream.

In the following example an object of class `Insertable` is directly inserted; an object of the class `Convertor` uses the conversion operator; an object of the class `Error` cannot be inserted since it does not define an insertion operator and the type returned by its conversion operator cannot be inserted either (`Text` does define an `operator int() const`, but the fact that a `Text` itself cannot be inserted causes the error):

        #include <iostream>
        #include <string>
        using namespace std;

        struct Insertable
        {
            operator int() const
            {
                cout << "op int()\n";
                return 0;
            }
        };
        ostream &operator<<(ostream &out, Insertable const &ins)
        {
            return out << "insertion operator";
        }
        struct Convertor
        {
            operator Insertable() const
            {
                return Insertable();
            }
        };
        struct Text
        {
            operator int() const
            {
                return 1;
            }
        };
        struct Error
        {
            operator Text() const
            {
                return Text{};
            }
        };

        int main()
        {
            Insertable insertable;
            cout << insertable << '\n';
            Convertor convertor;
            cout << convertor << '\n';
            Error error;
            cout << error << '\n';
        }

Some final remarks regarding conversion operators:

- A conversion operator should be a `natural extension' of the facilities of the object. For example, the stream classes define `operator bool()`, allowing constructions like `if (cin)`.
- A conversion operator usually returns an rvalue. It does so to enforce data-hiding and because it is the intended use of the conversion operator. Defining a conversion operator as an lvalue (e.g., defining an `operator int &()` conversion operator) opens up a back door, and the operator can only be used as lvalue when explicitly called (as in: `x.operator int&() = 5`). Don't normally use it, although there are exceptions to this rule (cf. section 11.4).
- Conversion operators are normally defined as `const` member functions as they normally don't modify their object's data members (but again: see section 11.4).
- Conversion operators returning composed objects should return const references to these objects whenever possible to avoid calling the composed object's copy constructor.

## 11.4: An alternative implementation of the `byte' type

In chapter 3 the `std::byte` type was introduced. It offers bit-wise and comparison operators but lacks other arithmetic operators as well as insertion and extraction operators, which may render it less useful. Fortunately, using the facilities provided by operator overloading a more generically useful byte-type can be developed.

In this section we develop a class `Byte` offering all facilities of numeric types, as well as insertion and extraction operators, while the size of a `Byte` object equals the size of an `unsigned char`: 1 byte.

A size 1 `Byte` type is realized by defining a class `Byte` having a single `uint8_t` data member. Insertion and extraction operators are provided by free functions. The class `Byte`, therefore, starts as follows:

        #include <iostream>
        #include <cstdint>          // uint8_t

        class Byte
        {
            uint8_t d_byte;

All the class's member functions are public: `Byte` objects can be defined using the default constructor, the copy constructor, and a constructor accepting any argument that can be converted to a `uint8_t`:

                Byte();                     // CC available by default
                Byte(uint8_t byte);

`Byte` objects can be used as lvalues, so assignment operators must be provided. The first (default) assignment operator handles assignment of `Byte` objects, while the second assignment operator handles assignment of numeric types which can be converted to `uint8_t` values:

                Byte &operator=(Byte const &rhs) = default;
                Byte &operator=(uint8_t rhs);

Conversion operators are provided so `Byte` objects can be used in situations where `uint8_t` values are used:

                operator uint8_t &();
                operator uint8_t() const;

Athough conversion operators usually return const references, an excption is made for `Byte` because of its semantics: as a `Byte` is essentially a wrapper around a `uint8_t` a non-const conversion operator is provided allowing the use of arithmetic assignment operators. A statement like `byte += 13` (having defined `Byte byte`) is compiled as `byte.operator() = 13`, which requires the non-const conversion operator.

Most members require a single statement and can very well be implemented inline. Here are their implementations:

        inline Byte::Byte()
        :
            d_byte(0)
        {}

        inline Byte::Byte(uint8_t byte)
        :
            d_byte(byte)
        {}

        Byte &Byte::operator=(uint8_t rhs)
        {
            d_byte = rhs;
            return *this;
        }

        inline Byte::operator uint8_t &()
        {
            return d_byte;
        }

        inline Byte::operator uint8_t () const // 16_t
        {
            return d_byte;
        }

The insertion and extraction operators act identically to the standard insertion and extraction operators for `uint8_t` type values: they insert and extract the `char` representation of the `Byte`'s value, because that's what insertion and extraction operators do: they process text. Here are their one-line implementations, using the conversion operators to insert or assign the `Byte's d_byte` value:

        inline std::ostream &operator<<(std::ostream &out, Byte const &byte)
        {
            return out << byte.operator uint8_t();
        }

        inline std::istream &operator>>(std::istream &in, Byte &byte)
        {
            return in >> byte.operator uint8_t &();
        }

To write the `d_byte's` binary value the stream's `write` member should be used in the way it's always used: reinterpret a `Byte` as a `char const *` and write a single byte. Reading a `Byte`'s binary value is implemented analogously, using the stream's `read` member.

Finally, here are some examples of how `Byte` variables can be used in practice:

        using namespace std;

        int main()
        {
            Byte b1;            // default: d_byte = 0
            Byte b2{ 12 };      // construct from an int
            Byte b3{ b2 };      // copy-construct

            b1 = 65;            // direct assignment
            b1 += 20;           // arithmetic assignment

            b1 <<= 1;           // shift-assignments
            b1 >>= 1;

            b1 |= 1;            // bit-or assignment

            uint8_t u8 = b1;    // assign Byte to an uint8_t

                                // some stream insertions
            cout << sizeof(Byte) << ',' << (b1 < b2) << ',' <<
                    b1 << ',' << b3 << ',' << u8 << '\n';

                                // using 'write'
            cout.write(reinterpret_cast<char const *>(&b1), 1) << '\n';
        }

        // output:
        //  hex values                                 text ( . : not printable)
        //  31 2C 30 2C 55 2C 0C 2C 55 0A 55 0A        1,0,U,.,U.U.

## 11.5: The keyword `explicit'

Conversions are not only performed by conversion operators, but also by constructors accepting one argument (i.e., constructors having one or multiple parameters, specifying default argument values for all parameters or for all but the first parameter).

Assume a data base class `DataBase` is defined in which `Person` objects can be stored. It defines a `Person *d_data` pointer, and so it offers a copy constructor and an overloaded assignment operator.

In addition to the copy constructor `DataBase` offers a default constructor and several additional constructors:

- `DataBase(Person const &)`: the `DataBase` initially contains a single `Person` object;
- `DataBase(istream &in)`: the data about multiple persons are read from `in`.
- `DataBase(size_t count, istream &in = cin)`: the data of `count` persons are read from `in`, by default the standard input stream.

The above constructors all are perfectly reasonable. But they also allow the compiler to compile the following code without producing any warning at all:

        DataBase db;
        DataBase db2;
        Person person;

        db2 = db;           // 1
        db2 = person;       // 2
        db2 = 10;           // 3
        db2 = cin;          // 4

Statement 1 is perfectly reasonable: `db` is used to redefine `db2`. Statement 2 might be understandable since we designed `DataBase` to contain `Person` objects. Nevertheless, we might question the logic that's used here as a `Person` is not some kind of `DataBase`. The logic becomes even more opaque when looking at statements 3 and 4. Statement 3 in effect waits for the data of 10 persons to appear at the standard input stream. Nothing like that is suggested by `db2 = 10`.

Implicit promotions are used with statements 2 through 4. Since constructors accepting, respectively a `Person`, an `istream`, and a `size_t` and an `istream` have been defined for `DataBase` and since the assignment operator expects a `DataBase` right-hand side (rhs) argument the compiler first converts the rhs arguments to anonymous `DataBase` objects which are then assigned to `db2`.

It is good practice to prevent implicit promotions by using the `explicit` modifier when declaring a constructor. Constructors using the `explicit` modifier can only be used to construct objects explicitly. Statements 2-4 would not have compiled if the constructors expecting one argument would have been declared using `explicit`. E.g.,

        explicit DataBase(Person const &person);
        explicit DataBase(size_t count, std:istream &in);

Having declared all constructors accepting one argument as `explicit` the above assignments would have required the explicit specification of the appropriate constructors, thus clarifying the programmer's intent:

        DataBase db;
        DataBase db2;
        Person person;

        db2 = db;                   // 1
        db2 = DataBase{ person };   // 2
        db2 = DataBase{ 10 };       // 3
        db2 = DataBase{ cin };      // 4

As a rule of thumb prefix one argument constructors with the `explicit` keyword unless implicit promotions are perfectly natural (`string`'s `char const *` accepting constructor is a case in point).

### 11.5.1: Explicit conversion operators

In addition to explicit constructors, C++ supports explicit conversion operators.

For example, a class might define `operator bool() const` returning `true` if an object of that class is in a usable state and `false` if not. Since the type `bool` is an arithmetic type this could result in unexpected or unintended behavior. Consider:

        void process(bool value);

        class StreamHandler
        {
            public:
                operator bool() const;      // true: object is fit for use
                ...
        };

        int fun(StreamHandler &sh)
        {
            int sx;

            if (sh)                         // intended use of operator bool()
                ... use sh as usual; also use `sx'

            process(sh);                    // typo: `sx' was intended
        }

In this example `process` unintentionally receives the value returned by `operator bool` using the implicit conversion from `bool` to `int`.

When defining `explicit` conversion operators implicit conversions like the one shown in the example are prevented. Such conversion operators can only be used in situations where the converted type is explicitly required (as in the condition clauses of `if` or `while` statements), or is explicitly requested using a `static_cast`. To declare an explicit bool conversion operator in class `StreamHandler`'s interface replace the above declaration by:

            explicit operator bool() const;

Since the C++14 standard `istreams` define an `explicit operator bool() const`. As a consequence:

        while (cin.get(ch)) // compiles OK
            ;

        bool fun1()
        {
            return cin;     // 'bool = istream' won't compile as
        }                   // istream defines 'explicit operator bool'

        bool fun1()
        {
            return static_cast<bool>(cin); // compiles OK
        }

## 11.6: Overloading increment and decrement operators

Overloading the increment operator (`operator++`) and decrement operator ( `operator--`) introduces a small problem: there are two versions of each operator, as they may be used as postfix operator (e.g., `x++`) or as prefix operator (e.g., `++x`).

Used as postfix operator, the value's object is returned as an rvalue, temporary const object and the post-incremented variable itself disappears from view. Used as prefix operator, the variable is incremented, and its value is returned as lvalue and it may be altered again by modifying the prefix operator's return value. Whereas these characteristics are not required when the operator is overloaded, it is strongly advised to implement these characteristics in any overloaded increment or decrement operator.

Suppose we define a wrapper class around the `size_t` value type. Such a class could offer the following (partially shown) interface:

        class Unsigned
        {
            size_t d_value;

            public:
                Unsigned();
                explicit Unsigned(size_t init);

                Unsigned &operator++();
        }

The class's last member declares the prefix overloaded increment operator. The returned lvalue is `Unsigned &`. The member is easily implemented:

        Unsigned &Unsigned::operator++()
        {
            ++d_value;
            return *this;
        }

To define the postfix operator, an overloaded version of the operator is defined, expecting a (dummy) `int` argument. This might be considered a kludge, or an acceptable application of function overloading. Whatever your opinion in this matter, the following can be concluded:

- Overloaded increment and decrement operators without parameters are prefix operators, and should return references to the current object.
- Overloaded increment and decrement operators having an int parameter are postfix operators, and should return a value which is a copy of the object at the point where its postfix operator is used.

The postfix increment operator is declared as follows in the class `Unsigned`'s interface:

        Unsigned operator++(int);

It may be implemented as follows:

        Unsigned Unsigned::operator++(int)
        {
            Unsigned tmp{ *this };
            ++d_value;
            return tmp;
        }

Note that the operator's parameter is not used. It is only part of the implementation to disambiguate the prefix- and postfix operators in implementations and declarations.

In the above example the statement incrementing the current object offers the nothrow guarantee as it only involves an operation on a primitive type. If the initial copy construction throws then the original object is not modified, if the return statement throws the object has safely been modified. But incrementing an object could itself throw exceptions. How to implement the increment operators in that case? Once again, `swap` is our friend. Here are the pre- and postfix operators offering the strong guarantee when the member `increment` performing the increment operation may throw:

        Unsigned &Unsigned::operator++()
        {
            Unsigned tmp{ *this };
            tmp.increment();
            swap(tmp);
            return *this;
        }
        Unsigned Unsigned::operator++(int)
        {
            Unsigned tmp{ *this };
            tmp.increment();
            swap(tmp);
            return tmp;
        }

Both operators first create copies of the current objects. These copies are incremented and then swapped with the current objects. If `increment` throws the current objects remain unaltered; the swap operations ensure that the correct objects are returned (the incremented object for the prefix operator, the original object for the postfix operator) and that the current objects become the incremented objects.

When calling the increment or decrement operator using its full member function name then any `int` argument passed to the function results in calling the postfix operator. Omitting the argument results in calling the prefix operator. Example:

        Unsigned uns{ 13 };

        uns.operator++();     // prefix-incrementing uns
        uns.operator++(0);    // postfix-incrementing uns

Both the prefix and postfix increment and decrement operators are deprecated when applied to `bool` type of variables. In situations where a postfix increment operator could be useful the `std::exchange` (cf. section 19.1.13) should be used.

## 11.7: Overloading binary operators

In various classes overloading binary operators (like `operator+`) can be a very natural extension of the class's functionality. For example, the `std::string` class has various overloaded `operator+` members.

Most binary operators come in two flavors: the plain binary operator (like the `+` operator) and the compound binary assignment operator (like `operator+=`). Whereas the plain binary operators return values, the compound binary assignment operators usually return references to the objects for which the operators were called. For example, with `std::string` objects the following code (annotations below the example) may be used:

        std::string s1;
        std::string s2;
        std::string s3;

        s1 = s2 += s3;                  // 1
        (s2 += s3) + " postfix";        // 2
        s1 = "prefix " + s3;            // 3
        "prefix " + s3 + "postfix";     // 4

- at `// 1` the content of `s3` is added to `s2`. Next, `s2` is returned, and its new content is assigned to `s1`. Note that `+=` returns `s2`.
- at `// 2` the content of `s3` is also added to `s2`, but as `+=` returns `s2` itself, it's possible to add some more to `s2`
- at `// 3` the `+` operator returns a `std::string` containing the concatenation of the text `prefix` and the content of `s3`. This string returned by the `+` operator is thereupon assigned to `s1`.
- at `// 4` the `+` operator is applied twice. The effect is:
  1. The first `+` returns a `std::string` containing the concatenation of the text `prefix` and the content of `s3`.
  2. The second `+` operator takes this returned string as its left hand value, and returns a string containing the concatenated text of its left and right hand operands.
  3. The string returned by the second `+` operator represents the value of the expression.

Now consider the following code, in which a class `Binary` supports an overloaded `operator+`:

        class Binary
        {
            public:
                Binary();
                Binary(int value);
                Binary operator+(Binary const &rhs);
        };

        int main()
        {
            Binary b1;
            Binary b2{ 5 };

            b1 = b2 + 3;            // 1
            b1 = 3 + b2;            // 2
        }

Compilation of this little program fails for statement `// 2`, with the compiler reporting an error like:

        error: no match for 'operator+' in '3 + b2'

Why is statement `// 1` compiled correctly whereas statement `// 2` won't compile?

In order to understand this remember promotions. As we have seen in section 11.5, constructors expecting single arguments may implicitly be activated when an argument of an appropriate type is provided. We've already encountered this with `std::string` objects, where NTBSs may be used to initialize `std::string` objects.

Analogously, in statement `// 1`, `operator+` is called, using `b2` as its left-hand side operand. This operator expects another `Binary` object as its right-hand side operand. However, an `int` is provided. But as a constructor `Binary(int)` exists, the `int` value can be promoted to a `Binary` object. Next, this `Binary` object is passed as argument to the `operator+` member.

Unfortunately, in statement `// 2` promotions are not available: here the `+` operator is applied to an `int`-type lvalue. An `int` is a primitive type and primitive types have no knowledge of `constructors', `member functions' or `promotions'.

How, then, are promotions of left-hand operands implemented in statements like `"prefix " + s3`? Since promotions can be applied to function arguments, we must make sure that both operands of binary operators are arguments. This implies that plain binary operators supporting promotions for either their left-hand side operand or right-hand side operand should be declared as free operators, also called free functions.

Functions like the plain binary operators conceptually belong to the class for which they implement these operators. Consequently they should be declared in the class's header file. We cover their implementations shortly, but here is our first revision of the declaration of the class `Binary`, declaring an overloaded `+` operator as a free function:

        class Binary
        {
            public:
                Binary();
                Binary(int value);
        };

        Binary operator+(Binary const &lhs, Binary const &rhs);

After defining binary operators as free functions, several promotions are available:

- If the left-hand operand is of the intended class type, the right hand argument is promoted whenever possible;
- If the right-hand operand is of the intended class type, the left hand argument is promoted whenever possible;
- No promotions occur when neither operand is of the intended class type;
- An ambiguity occurs when promotions to different classes are possible for the two operands. For example:

          class A;

          class B
          {
              public:
                  B(A const &a);
          };

          class A
          {
              public:
                  A();
                  A(B const &b);
          };

          A operator+(A const &a, B const &b);
          B operator+(B const &b, A const &a);

          int main()
          {
              A a;

              a + a;
          };

  Here, both overloaded `+` operators are possible candidates when compiling the statement `a + a`. The ambiguity must be solved by explicitly promoting one of the arguments, e.g., `a + B{a}`, which enables the compiler to resolve the ambiguity to the first overloaded `+` operator.

The next step consists of implementing the required overloaded binary compound assignment operators, having the form `@=`, where `@` represents a binary operator. As these operators always have left-hand side operands which are object of their own classes, they are implemented as genuine member functions. Compound assignment operators usually return references to the objects for which the binary compound assignment operators were requested, as these objects might be modified in the same statement. E.g., `(s2 += s3) + " postfix"`.

Here is our second revision of the class `Binary`, showing the declaration of the plain binary operator as well as the corresponding compound assignment operator:

        class Binary
        {
            public:
                Binary();
                Binary(int value);

                Binary &operator+=(Binary const &rhs);
        };

        Binary operator+(Binary const &lhs, Binary const &rhs);

How should the compound addition assignment operator be implemented? When implementing compound binary assignment operators the strong guarantee should always be kept in mind: if the operation might throw use a temporary object and swap. Here is our implementation of the compound assignment operator:

        Binary &Binary::operator+=(Binary const &rhs)
        {
            Binary tmp{ *this };
            tmp.add(rhs);           // this might throw
            swap(tmp);
            return *this;
        }

It's easy to implement the free binary operator: the `lhs` argument is copied into a `Binary tmp` to which the `rhs` operand is added. Then `tmp` is returned, using copy elision. The class `Binary` declares the free binary operator as a friend (cf. chapter 15), so it can call `Binary's add` member:

        class Binary
        {
            friend Binary operator+(Binary const &lhs, Binary const &rhs);

            public:
                Binary();
                Binary(int value);

                Binary &operator+=(Binary const &other);

            private:
                void add(Binary const &other);
        };

The binary operator's implementation becomes:

        Binary operator+(Binary const &lhs, Binary const &rhs)
        {
            Binary tmp{ lhs };
            tmp.add(rhs);
            return tmp;
        }

If the class `Binary` is move-aware then it's attractive to add move-aware binary operators. In this case we also need operators whose left-hand side operands are rvalue references. When a class is move aware various interesting implementations are suddenly possible, which we encounter below, and in the next (sub)section. First have a look at the signature of such a binary operator (which should also be declared as a friend in the class interface):

        Binary operator+(Binary &&lhs, Binary const &rhs);

Since the lhs operand is an rvalue reference, we can modify it ad lib. Binary operators are commonly designed as factory functions, returning objects created by those operators. However, the (modified) object referred to by `lhs` should itself not be returned. As stated in the C++ standard,

> A temporary object bound to a reference parameter in a function call persists until the completion of the full-expression containing the call.

and furthermore:

> The lifetime of a temporary bound to the returned value in a function return statement is not extended; the temporary is destroyed at the end of the full-expression in the return statement.

In other words, a temporary object cannot itself be returned as the function's return value: a `Binary &&` return type should therefore not be used. Therefore functions implementing binary operators are factory functions (note, however, that the returned object may be constructed using the class's move constructor whenever a temporary object has to be returned).

Alternatively, the binary operator can first create an object by move constructing it from the operator's lhs operand, performing the binary operation on that object and the operator's rhs operand, and then return the modified object (allowing the compiler to apply copy elision). It's a matter of taste which one is preferred.

Here are the two implementations. Because of copy elision the explicitly defined `ret` object is created in the location of the return value. Both implementations, although they appear to be different, show identical run-time behavior:

                    // first implementation: modify lhs
        Binary operator+(Binary &&lhs, Binary const &rhs)
        {
            lhs.add(rhs);
            return std::move(lhs);
        }
                    // second implementation: move construct ret from lhs
        Binary operator+(Binary &&lhs, Binary const &rhs)
        {
            Binary ret{ std::move(lhs) };
            ret.add(rhs);
            return ret;
        }

Now, when executing expressions like (all `Binary` objects) `b1 + b2 + b3` the following functions are called:

        copy operator+          = b1 + b2
        Copy constructor        = tmp(b1)
            adding              = tmp.add(b2)
        copy elision            : tmp is returned from b1 + b2

        move operator+          = tmp + b3
        adding                  = tmp.add(b3)
        Move construction       = tmp2(move(tmp)) is returned

But we're not there yet: in the next section we encounter possibilities for several more interesting implementations, in the context of compound assignment operators.

### 11.7.1: Member function reference bindings (& and &&)

We've seen that binary operators (like `operator+`) can be implemented very efficiently, but require at least move constructors.

An expression like

        Binary{} + varB + varC + varD

therefore returns a move constructed object representing `Binary{} + varB`, then another move constructed object receiving the first return value and `varC`, and finally yet another move constructed object receiving the second returned object and `varD` as its arguments.

Now consider the situation where we have a function defining a `Binary &&` parameter, and a second `Binary const &` parameter. Inside that function these values need to be added, and their sum is then passed as argument to two other functions. We could do this:

        void fun1(Binary &&lhs, Binary const &rhs)
        {
            lhs += rhs;
            fun2(lhs);
            fun3(lhs);
        }

But realize that when using `operator+=` we first construct a copy of the current object, so a temporary object is available to perform the addition on, and then swap the temporary object with the current object to commit the results. But wait! Our lhs operand already is a temporary object. So why create another?

In this example another temporary object is indeed not required: `lhs` remains in existence until `fun1` ends. But different from the binary operators the binary compound assignment operators don't have explicitly defined left-hand side operands. But we still can inform the compiler that a particular member (so, not merely compound assignment operators) should only be used when the objects calling those members is an anonymous temporary object, or a non-anonymous (modifiable or non-modifiable) object. For this we use reference bindings a.k.a. reference qualifiers.

Reference bindings consist of a reference token (`&`), optionally preceded by `const`, or an rvalue reference token (`&&`). Such reference qualifiers are immediately affixed to the function's head (this applies to the declaration and the implementation alike). Functions provided with rvalue reference bindings are selected by the compiler when used by anonymous temporary objects, whereas functions provided with lvalue reference bindings are selected by the compiler when used by other types of objects.

Reference qualifiers allow us to fine-tune our implementations of compound assignment operators like `operator+=`. If we know that the object calling the compound assignment operator is itself a temporary, then there's no need for a separate temporary object. The operator may directly perform its operation and could then return itself as an rvalue reference. Here is the implementation of `operator+=` tailored to being used by temporary objects:

        Binary &&Binary::operator+=(Binary const &rhs) &&
        {
            add(rhs);                   // directly add rhs to *this,
            return std::move(*this);    // return the temporary object itself
        }

This implementation is about as fast as it gets. But be careful: in the previous section we learned that a temporary is destroyed at the end of the full expression of a return stattement. In this case, however, the temporary already exists, and so (also see the previous section) it should persist until the expression containing the (`operator+=`) function call is completed. As a consequence,

        cout << (Binary{} += existingBinary) << '\n';

is OK, but

        Binary &&rref = (Binary{} += existingBinary);
        cout << rref << '\n';

is not, since `rref` becomes a dangling reference immediately after its initialization.

A full-proof alternative implementation of the rvalue-reference bound `operator+=` returns a move-constructed copy:

        Binary Binary::operator+=(Binary const &rhs) &&
        {
            add(rhs);                   // directly add rhs to *this,
            return std::move(*this);    // return a move constructed copy
        }

The price to pay for this full-proof implementation is an extra move construction. Now, using the previous example (using `rref`), `operator+=` returns a copy of the `Binary{}` temporary, which is still a temporary object which can safely be referred to by `rref`.

Which implementation to use may be a matter of choice: if users of `Binary` know what they're doing then the former implementation can be used, since these users will never use the above `rref` initialization. If you're not so sure about your users, use the latter implementation: formally your users will do something they shouldn't do, but there's no penalty for that.

For the compound assignment operator called by an lvalue reference (i.e., a named object) we use the implementation for `operator+=` from the previous section (note the reference qualifier):

        Binary &Binary::operator+=(Binary const &rhs) &
        {
            Binary tmp(*this);
            tmp.add(rhs);           // this might throw
            swap(tmp);
            return *this;
        }

With this implementation adding `Binary` objects to each other (e.g., `b1 += b2 += b3`) boils down to

        operator+=    (&)       = b2 += b3
        Copy constructor        = tmp(b2)
            adding              = tmp.add(b3)
            swap                = b2 <-> tmp
        return                  = b2

        operator+=    (&)       = b1 += b2
        Copy constructor        = tmp(b1)
            adding              = tmp.add(b2)
            swap                = b1 <-> tmp
        return                  = b1

When the leftmost object is a temporary then a copy construction and swap call are replaced by the construction of an anonymous object. E.g., with `Binary{} += b2 += b3` we observe:

        operator+=    (&)       = b2 += b3
        Copy constructor        = tmp(b2)
            adding              = tmp.add(b3)
            swap                = b2 <-> tmp

        Anonymous object        = Binary{}

        operator+=    (&&)      = Binary{} += b2
            adding              = add(b2)

        return                  = move(Binary{})

For `Binary &Binary::operator+=(Binary const &rhs) &` an alternative implementation exists, merely using a single return statement, but in fact requiring two extra function calls. It's a matter of taste whether you prefer writing less code or executing fewer function calls:

        Binary &Binary::operator+=(Binary const &rhs) &
        {
            return *this = Binary{ *this } += rhs;
        }

Notice that the implementations of `operator+` and `operator+=` are independent of the actual definition of the class `Binary`. Adding standard binary operators to a class (i.e., operators operating on arguments of their own class types) can therefore easily be realized.

### 11.7.2: The three-way comparison operator `<=>'

The `C++26` standard added the three-way comparison operator `<=>`, also known as the spaceship operator, to the language.

This operator is closely related to comparison classes, covered in section 18.7. At this point we focus on using the `std::strong_ordering` class: the examples of the spaceship operator presented in this section all return `strong_ordering` objects. These objects are

- `strong_ordering::equal` if both operands are equal;
- `strong_ordering::less` if the left-hand side operand is smaller than the right-hand side operand;
- `strong_ordering::greater` if the left-hand side operand is greater than the right-hand side operand.

Standard operand conversions are handled by the compiler. Note that

- if one of the operands is of type `bool`, then the other operand must also be of type `bool`;
- narrowing conversions, except from integral types to floating point types, are not allowed;
- when the operands are of identical enumeration types their values are converted to the underlying numeric integral type, which values are then compared.

Other standard conversions, like lvalue transformations and qualification conversions (cf. section 21.4), are automatically performed.

Now about the spaceship operator itself. Why would you want it? Of course, if it's defined then you can use it. As it's available for integral numeric types the following correctly compiles:

        auto isp =    3 <=> 4;

whereafter `isp's` value can be compared to available outcome-values:

        cout << ( isp == strong_ordering::less ? "less\n" : "not less\n" );

But that by itself doesn't make the spaceship operator all too interesting. What does make it interesting is that, in combination with `operator==`, it handles all comparison operators. So after providing a class with `operator==` and `operator<=>` its objects can be compared for equality, inequality, and they can be ordered by `<, <=, >,` and `>=`. As an example consider books. To book owners the titles and author names are the books' important characterstics. To sort them on book shelfs we must use `operator<`, to find a particular book we use `operator==`, to determine whether two books are different we use `operator!=` and if you want to order them in an country where Arabic is the main language you might want to sort them using `operator>` considering that the prevalent reading order in those countries is from right to left. Ignoring constructors, destructors and other members, then this is the interface of our class `Book` (note the inclusion of the `<compare>` header file, containing the declarations of the comparison classes):

        #include <string>
        #include <compare>

        class Book
        {
            friend bool operator==(Book const &lhs, Book const &rhs);
            friend std::strong_ordering operator<=>(Book const &lhs,
                                                    Book const &rhs);
            std::string d_author;
            std::string d_title;

            // ...
        };

Both friend-functions are easy to implement:

        bool operator==(Book const &lhs, Book const &rhs)
        {
            return lhs.d_author == rhs.d_author and lhs.d_title == rhs.d_title;
        }

        strong_ordering operator<=>(Book const &lhs, Book const &rhs)
        {
            return lhs.d_author < rhs.d_author  ? strong_ordering::less     :
                   lhs.d_author > rhs.d_author  ? strong_ordering::greater  :
                   lhs.d_title  < rhs.d_title   ? strong_ordering::less     :
                   lhs.d_title  > rhs.d_title   ? strong_ordering::greater  :
                                                  strong_ordering::equal;
        }

And that's it! Now all comparison operators (and of course the spaceship operator itself) are available. The following now compiles flawlessly:

        void books(Book const &b1, Book const &b2)
        {
            cout << (b1 == b2) << (b1 != b2) << (b1 <  b2) <<
                    (b1 <= b2) << (b1 >  b2) << (b1 >= b2) << '\n';
        }

calling `books` for two identical books inserts 100101 into `cout`.

The spaceship operator is available for integral numeric types and may have been defined for class types. E.g., it is defined for `std::string`. It is not automatically available for floating point types.

## 11.8: Overloading `operator new(size_t)'

When `operator new` is overloaded, it must define a `void *` return type, and its first parameter must be of type `size_t`. The default `operator new` defines only one parameter, but overloaded versions may define multiple parameters. The first one is not explicitly specified but is deduced from the size of objects of the class for which `operator new` is overloaded. In this section overloading `operator new` is discussed. Overloading `new[]` is discussed in section 11.10.

It is possible to define multiple versions of the `operator new`, as long as each version defines its own unique set of arguments. When overloaded `operator new` members must dynamically allocate memory they can do so using the global `operator new`, applying the scope resolution operator `::`. In the next example the overloaded `operator new` of the class `String` initializes the substrate of dynamically allocated `String` objects to 0-bytes:

        #include <cstring>
        #include <iosfwd>

        class String
        {
            std::string *d_data;

            public:
                void *operator new(size_t size)
                {
                    return memset(::operator new(size), 0, size);
                }
                bool empty() const
                {
                    return d_data == 0;
                }
        };

The above `operator new` is used in the following program, illustrating that even though `String`'s default constructor does nothing the object's data member `d_data` is initialized to zero:

        #include "string.h"
        #include <iostream>
        using namespace std;

        int main()
        {
            String *sp = new String;

            cout << boolalpha << sp->empty() << '\n';   // shows: true
        }

At `new String` the following took place:

- First, `String::operator new` was called, allocating and initializing a block of memory, the size of a `String` object.
- Next, a pointer to this block of memory was passed to the (default) `String` constructor. Since no constructor was defined, the constructor itself didn't do anything at all.

As `String::operator new` initialized the allocated memory to zero bytes the allocated `String` object's `d_data` member had already been initialized to a 0-pointer by the time it started to exist.

All member functions (including constructors and destructors) we've encountered so far define a (hidden) pointer to the object on which they should operate. This hidden pointer becomes the function's `this` pointer.

In the next example of pseudo C++ code, the pointer is explicitly shown to illustrate what's happening when `operator new` is used. In the first part a `String` object `str` is directly defined, in the second part of the example the (overloaded) `operator new` is used:

        String::String(String *const this);     // real prototype of the default
                                                // constructor

        String *sp = new String;                // This statement is implemented
                                                // as follows:

        String *sp = static_cast<String *>(            // allocation
                            String::operator new(sizeof(String))
                     );
        String::String{ sp };                          // initialization

In the above fragment the member functions were treated as object-less member functions of the class `String`. Such members are called static member functions (cf. chapter 8). Actually, `operator new` is such a static member function. Since it has no `this` pointer it cannot reach data members of the object for which it is expected to make memory available. It can only allocate and initialize the allocated memory, but cannot reach the object's data members by name as there is as yet no data object layout defined.

Following the allocation, the memory is passed (as the `this` pointer) to the constructor for further processing.

`Operator new` can have multiple parameters. The first parameter is initialized as an implicit argument and is always a `size_t` parameter. Additional overloaded operators may define additional parameters. An interesting additional `operator new` is the placement new operator. With the placement new operator a block of memory has already been set aside and one of the class's constructors is used to initialize that memory. Overloading placement new requires an `operator new` having two parameters: `size_t` and `char *`, pointing to the memory that was already available. The `size_t` parameter is implicitly initialized, but the remaining parameters must explicitly be initialized using arguments to `operator new`. Hence we reach the familiar syntactical form of the placement new operator in use:

        char buffer[sizeof(String)];        // predefined memory
        String *sp = new(buffer) String;    // placement new call

The declaration of the placement new operator in our class `String` looks like this:

        void *operator new(size_t size, char *memory);

It could be implemented like this (also initializing the `String`'s memory to 0-bytes):

        void *String::operator new(size_t size, char *memory)
        {
            return memset(memory, 0, size);
        }

Any other overloaded version of `operator new` could also be defined. Here is an example showing the use and definition of an overloaded `operator new` storing the object's address immediately in an existing array of pointers to `String` objects (assuming the array is large enough):

            // use:
        String *next(String **pointers, size_t *idx)
        {
            return new(pointers, (*idx)++) String;
        }

            // implementation:
        void *String::operator new(size_t size, String **pointers, size_t idx)
        {
            return pointers[idx] = ::operator new(size);
        }

## 11.9: Overloading `operator delete(void *)'

The `delete` operator may also be overloaded. In fact it's good practice to overload `operator delete` whenever `operator new` is also overloaded.

`Operator delete` must define a `void *` parameter. A second overloaded version defining a second parameter of type `size_t` is related to overloading `operator new[]` and is discussed in section 11.10.

Overloaded `operator delete` members return `void`.

The `home-made' `operator delete` is called when deleting a dynamically allocated object after executing the destructor of the associated class. So, the statement

        delete ptr;

with `ptr` being a pointer to an object of the class `String` for which the operator `delete` was overloaded, is a shorthand for the following statements:

        ptr->~String(); // call the class's destructor

                        // and do things with the memory pointed to by ptr
        String::operator delete(ptr);

The overloaded `operator delete` may do whatever it wants to do with the memory pointed to by `ptr`. It could, e.g., simply delete it. If that would be the preferred thing to do, then the default `delete` operator can be called using the `::` scope resolution operator. For example:

        void String::operator delete(void *ptr)
        {
            // any operation considered necessary, then, maybe:
            ::delete ptr;
        }

To declare the above overloaded `operator delete` simply add the following line to the class's interface:

        void operator delete(void *ptr);

Like `operator new operator delete` is a static member function (see also chapter 8).

## 11.10: Operators `new[]' and `delete[]'

In sections 9.1.1, 9.1.2 and 9.2.1 `operator new[]` and `operator delete[]` were introduced. Like `operator new` and `operator delete` the operators `new[]` and `delete[]` may be overloaded.

As it is possible to overload `new[]` and `delete[]` as well as `operator new` and `operator delete`, one should be careful in selecting the appropriate set of operators. The following rule of thumb should always be applied:

> If `new` is used to allocate memory, `delete` should be used to deallocate memory. If `new[]` is used to allocate memory, `delete[]` should be used to deallocate memory.

By default these operators act as follows:

- `operator new` is used to allocate a single object or primitive value. With an object, the object's constructor is called.
- `operator delete` is used to return the memory allocated by `operator new`. Again, with class-type objects, the class's destructor is called.
- `operator new[]` is used to allocate a series of primitive values or objects. If a series of objects is allocated, the class's default constructor is called to initialize each object individually.
- `operator delete[]` is used to delete the memory previously allocated by `new[]`. If objects were previously allocated, then the destructor is called for each individual object. Be careful, though, when pointers to objects were allocated. If pointers to objects were allocated the destructors of the objects to which the allocated pointers point won't automatically be called. A pointer is a primitive type and so no further action is taken when it is returned to the common pool.

### 11.10.1: Overloading `new[]'

To overload `operator new[]` in a class (e.g., in the class `String`) add the following line to the class's interface:

        void *operator new[](size_t size);

The member's `size` parameter is implicitly provided and is initialized by C++'s run-time system to the amount of memory that must be allocated. Like the simple one-object `operator new` it should return a `void *`. The number of objects that must be initialized can easily be computed from `size / sizeof(String)` (and of course replacing `String` by the appropriate class name when overloading `operator new[]` for another class). The overloaded `new[]` member may allocate raw memory using e.g., the default `operator new[]` or the default `operator new`:

        void *operator new[](size_t size)
        {
            return ::operator new[](size);
            // alternatively:
            // return ::operator new(size);
        }

Before returning the allocated memory the overloaded `operator new[]` has a chance to do something special. It could, e.g., initialize the memory to zero-bytes.

Once the overloaded `operator new[]` has been defined, it is automatically used in statements like:

        String *op = new String[12];

Like `operator new` additional overloads of `operator new[]` may be defined. One opportunity for an `operator new[]` overload is overloading placement new specifically for arrays of objects. This operator is available by default but becomes unavailable once at least one overloaded `operator new[]` is defined. Implementing placement `new` is not difficult. Here is an example, initializing the available memory to 0-bytes before returning:

        void *String::operator new[](size_t size, char *memory)
        {
            return memset(memory, 0, size);
        }

To use this overloaded operator, the second parameter must again be provided, as in:

        char buffer[12 * sizeof(String)];
        String *sp = new(buffer) String[12];

### 11.10.2: Overloading `delete[]'

To overload `operator delete[]` in a class `String` add the following line to the class's interface:

        void operator delete[](void *memory);

Its parameter is initialized to the address of a block of memory previously allocated by `String::new[]`.

There are some subtleties to be aware of when implementing `operator delete[]`. Although the addresses returned by `new` and `new[]` point to the allocated object(s), there is an additional `size_t` value available immediately before the address returned by `new` and `new[]`. This `size_t` value is part of the allocated block and contains the actual size of the block. This of course does not hold true for the placement `new` operator.

When a class defines a destructor the `size_t` value preceding the address returned by `new[]` does not contain the size of the allocated block, but the number of objects specified when calling `new[]`. Normally that is of no interest, but when overloading `operator delete[]` it might become a useful piece of information. In those cases `operator delete[]` does not receive the address returned by `new[]` but rather the address of the initial `size_t` value. Whether this is at all useful is not clear. By the time `delete[]`'s code is executed all objects have already been destroyed, so `operator delete[]` is only to determine how many objects were destroyed but the objects themselves cannot be used anymore.

Here is an example showing this behavior of `operator delete[]` for a minimal `Demo` class:

        struct Demo
        {
            size_t idx;
            Demo()
            {
                cout << "default cons\n";
            }
            ~Demo()
            {
                cout << "destructor\n";
            }
            void *operator new[](size_t size)
            {
                return ::operator new(size);
            }
            void operator delete[](void *vp)
            {
                cout << "delete[] for: " << vp << '\n';
                ::operator delete[](vp);
            }
        };

        int main()
        {
            Demo *xp;
            cout << ((int *)(xp = new Demo[3]))[-1] << '\n';
            cout << xp << '\n';
            cout << "==================\n";
            delete[] xp;
        }
        // This program displays (your 0x?????? addresses might differ, but
        // the difference between the two should be sizeof(size_t)):
        //  default cons
        //  default cons
        //  default cons
        //  3
        //  0x8bdd00c
        //  ==================
        //  destructor
        //  destructor
        //  destructor
        //  delete[] for: 0x8bdd008

Having overloaded `operator delete[]` for a class `String`, it will be used automatically in statements like:

            delete[] new String[5];

Operator `delete[]` may also be overloaded using an additional `size_t` parameter:

        void operator delete[](void *p, size_t size);

Here `size` is automatically initialized to the size (in bytes) of the block of memory to which `void *p` points. If this form is defined, then `void operator[](void *)` should not be defined, to avoid ambiguities. An example of this latter form of `operator delete[]` is:

        void String::operator delete[](void *ptr, size_t size)
        {
            cout << "deleting " << size << " bytes\n";
            ::operator delete[](ptr);
        }

Additional overloads of `operator delete[]` may be defined, but to use them they must explicitly be called as static member functions (cf. chapter 8). Example:

            // declaration:
        void String::operator delete[](void *ptr, ostream &out);
            // usage:
        String *xp = new String[3];
        String::operator delete[](xp, cout);

### 11.10.3: The `operator delete(void *, size_t)' family

As we've seen classes may overload their `operator delete` and `operator delete[]` members.

Since the C++14 standard the global `void operator delete(void *, size_t size)` and `void operator delete[](void *, size_t size)` functions can also be overloaded.

When a global sized deallocation function is defined, it is automatically used instead of the default, non-sized deallocation function. The performance of programs may improve if a sized deallocation function is available (cf. http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2013/n3663.html).

### 11.10.4: `new[]', `delete[]' and exceptions

When an exception is thrown while executing a `new[]` expression, what will happen? In this section we'll show that `new[]` is exception safe even when only some of the objects were properly constructed.

To begin, `new[]` might throw while trying to allocate the required memory. In this case a `bad_alloc` is thrown and we don't leak as nothing was allocated.

Having allocated the required memory the class's default constructor is going to be used for each of the objects in turn. At some point a constructor might throw. What happens next is defined by the C++ standard: the destructors of the already constructed objects are called and the memory allocated for the objects themselves is returned to the common pool. Assuming that the failing constructor offers the basic guarantee `new[]` is therefore exception safe even if a constructor may throw.

The following example illustrates this behavior. A request to allocate and initialize five objects is made, but after constructing two objects construction fails by throwing an exception. The output shows that the destructors of properly constructed objects are called and that the allocated substrate memory is properly returned:

        #include <iostream>
        using namespace std;

        static size_t count = 0;

        class X
        {
            int x;

            public:
                X()
                {
                    if (count == 2)
                        throw 1;
                    cout << "Object " << ++count << '\n';
                }
                ~X()
                {
                    cout << "Destroyed " << this << "\n";
                }
                void *operator new[](size_t size)
                {
                    cout << "Allocating objects: " << size << " bytes\n";
                    return ::operator new(size);
                }
                void operator delete[](void *mem)
                {
                    cout << "Deleting memory at " << mem << ", containing: " <<
                        *static_cast<int *>(mem) << "\n";
                    ::operator delete(mem);
                }
        };

        int main()
        try
        {
            X *xp = new X[5];
            cout << "Memory at " << xp << '\n';
            delete[] xp;
        }
        catch (...)
        {
            cout << "Caught exception.\n";
        }
        // Output from this program (your 0x??? addresses might differ)
        //  Allocating objects: 24 bytes
        //  Object 1
        //  Object 2
        //  Destroyed 0x8428010
        //  Destroyed 0x842800c
        //  Deleting memory at 0x8428008, containing: 5
        //  Caught exception.

## 11.11: Function Objects

Function Objects are created by overloading the function call operator `operator()`. By defining the function call operator an object masquerades as a function, hence the term function objects. Function objects are also known as functors.

Function objects are important when using generic algorithms. The use of function objects is preferred over alternatives like pointers to functions. The fact that they are important in the context of generic algorithms leaves us with a didactic dilemma. At this point in the C++ Annotations it would have been nice if generic algorithms would already have been covered, but for the discussion of the generic algorithms knowledge of function objects is required. This bootstrapping problem is solved in a well-known way: by ignoring the dependency for the time being, for now concentrating on the function object concept.

Function objects are objects for which `operator()` has been defined. Function objects are not just used in combination with generic algorithms, but also as a (preferred) alternative to pointers to functions.

Function objects are frequently used to implement predicate functions. Predicate functions return boolean values. Predicate functions and predicate function objects are commonly referred to as `predicates'. Predicates are frequently used by generic algorithms such as the count_if generic algorithm, covered in chapter 19, returning the number of times its function object has returned `true`. In the standard template library two kinds of predicates are used: unary predicates receive one argument, binary predicates receive two arguments.

Assume we have a class `Person` and an array of `Person` objects. Further assume that the array is not sorted. A well-known procedure for finding a particular `Person` object in the array is to use the function `lsearch`, which performs a linear search in an array. Example:

        Person &target = targetPerson();    // determine the person to find
        Person *pArray;
        size_t n = fillPerson(&pArray);

        cout << "The target person is";

        if (not lsearch(&target, pArray, &n, sizeof(Person), compareFunction))
            cout << " not";
        cout << " found\n";

The function `targetPerson` determines the person we're looking for, and `fillPerson` is called to fill the array. Then `lsearch` is used to locate the target person.

The comparison function must be available, as its address is one of the arguments of `lsearch`. It must be a real function having an address. If it is defined inline then the compiler has no choice but to ignore that request as inline functions don't have addresses. `CompareFunction` could be implemented like this:

        int compareFunction(void const *p1, void const *p2)
        {
            return *static_cast<Person const *>(p1)     // lsearch wants 0
                    !=                                  // for equal objects
                    *static_cast<Person const *>(p2);
        }

This, of course, assumes that the `operator!=` has been overloaded in the class `Person`. But overloading `operator!=` is no big deal, so let's assume that that operator is actually available.

On average `n / 2` times at least the following actions take place:

1. The two arguments of the compare function are pushed on the stack;
2. The value of the final parameter of `lsearch` is determined, producing `compareFunction`'s address;
3. The compare function is called;
4. Then, inside the compare function the address of the right-hand argument of the `Person::operator!=` argument is pushed on the stack;
5. `Person::operator!=` is evaluated;
6. The argument of the `Person::operator!=` function is popped off the stack;
7. The two arguments of the compare function are popped off the stack.

Using function objects results in a different picture. Assume we have constructed a function `PersonSearch`, having the following prototype (this, however, is not the preferred approach. Normally a generic algorithm is preferred over a home-made function. But for now we focus on `PersonSearch` to illustrate the use and implementation of a function object):

        Person const *PersonSearch(Person *base, size_t nmemb,
                                   Person const &target);

This function can be used as follows:

        Person &target = targetPerson();
        Person *pArray;
        size_t n = fillPerson(&pArray);

        cout << "The target person is";

        if (!PersonSearch(pArray, n, target))
            cout << " not";

        cout << "found\n";

So far, not much has been changed. We've replaced the call to `lsearch` with a call to another function: `PersonSearch`. Now look at `PersonSearch` itself:

        Person const *PersonSearch(Person *base, size_t nmemb,
                                    Person const &target)
        {
            for (int idx = 0; idx < nmemb; ++idx)
                if (target(base[idx]))
                    return base + idx;
            return 0;
        }

`PersonSearch` implements a plain linear search. However, in the for-loop we see `target(base[idx])`. Here `target` is used as a function object. Its implementation is simple:

        bool Person::operator()(Person const &other) const
        {
            return *this == other;
        }

Note the somewhat peculiar syntax: `operator()`. The first set of parentheses define the operator that is overloaded: the function call operator. The second set of parentheses define the parameters that are required for this overloaded operator. In the class header file this overloaded operator is declared as:

        bool operator()(Person const &other) const;

Clearly `Person::operator()` is a simple function. It contains but one statement, and we could consider defining it inline. Assuming we do, then this is what happens when `operator()` is called:

1. The address of the right-hand argument of the `Person::operator==` argument is pushed on the stack;
2. The `operator==` function is evaluated (which probably also is a semantic improvement over calling `operator!=` when looking for an object equal to a specified target object);
3. The argument of `Person::operator==` argument is popped off the stack.

Due to the fact that `operator()` is an inline function, it is not actually called. Instead `operator==` is called immediately. Moreover, the required stack operations are fairly modest.

Function objects may truly be defined inline. Functions that are called indirectly (i.e., using pointers to functions) can never be defined inline as their addresses must be known. Therefore, even if the function object needs to do very little work it is defined as an ordinary function if it is going to be called through pointers. The overhead of performing the indirect call may annihilate the advantage of the flexibility of calling functions indirectly. In these cases using inline function objects can result in an increase of a program's efficiency.

An added benefit of function objects is that they may access the private data of their objects. In a search algorithm where a compare function is used (as with `lsearch`) the target and array elements are passed to the compare function using pointers, involving extra stack handling. Using function objects, the target person doesn't vary within a single search task. Therefore, the target person could be passed to the function object's class constructor. This is in fact what happens in the expression `target(base[idx])` receiving as its only argument the subsequent elements of the array to search.

### 11.11.1: Constructing manipulators

In chapter 6 we saw constructions like `cout` << `hex` << `13` << to display the value 13 in hexadecimal format. One may wonder by what magic the `hex` manipulator accomplishes this. In this section the construction of manipulators like `hex` is covered.

Actually the construction of a manipulator is rather simple. To start, a definition of the manipulator is needed. Let's assume we want to create a manipulator `w10` which sets the field width of the next field to be written by the `ostream` object to 10. This manipulator is constructed as a function. The `w10` function needs to know about the `ostream` object in which the width must be set. By providing the function with an `ostream &` parameter, it obtains this knowledge. Now that the function knows about the `ostream` object we're referring to, it can set the width in that object.

Next, it must be possible to use the manipulator in an insertion sequence. This implies that the return value of the manipulator must be a reference to an `ostream` object also.

From the above considerations we're now able to construct our `w10` function:

        #include <ostream>
        #include <iomanip>

        std::ostream &w10(std::ostream &str)
        {
            return str << std::setw(10);
        }

The `w10` function can of course be used in a `stand alone' mode, but it can also be used as a manipulator. E.g.,

            #include <iostream>
            #include <iomanip>

            using namespace std;

            extern ostream &w10(ostream &str);

            int main()
            {
                w10(cout) << 3 << " ships sailed to America\n";
                cout << "And " << w10 << 3 << " more ships sailed too.\n";
            }

The `w10` function can be used as a manipulator because the `class ostream` has an overloaded `operator`<< accepting a pointer to a function expecting an `ostream &` and returning an `ostream &`. Its definition is:

        ostream &operator<<(ostream &(*func)(ostream &str))
        {
            return (*func)(*this);
        }

E.g., this `std::ostream &(*func)(std::ostream &str)` function is the signature of the `std::endl` manipulator.

In addition to the above overloaded `operator`<< another one is defined

        ios_base &operator<<(ios_base &(*func)(ios_base &base))
        {
            (*func)(*this);
            return *this;
        }

This latter function is used when inserting, e.g., `hex` or `internal`.

The above procedure does not work for manipulators requiring arguments. It is of course possible to overload `operator`<< to accept an `ostream` reference and the address of a function expecting an `ostream &` and, e.g., an `int`, but while the address of such a function may be specified with the <<-operator, the arguments itself cannot be specified. So, one wonders how the following construction has been implemented:

        cout << setprecision(3)

In this case the manipulator is defined as a macro. Macro's, however, are the realm of the preprocessor, and may easily suffer from unwelcome side-effects. In C++ programs they should be avoided whenever possible. The following section introduces a way to implement manipulators requiring arguments without resorting to macros, but using anonymous objects.

#### 11.11.1.1: Manipulators requiring arguments

Manipulators taking arguments are implemented as macros: they are handled by the preprocessor, and are not available beyond the preprocessing stage.

Manipulators, maybe requiring arguments, can also be defined without using macros. One solution, suitable for modifying globally available objects (like `cin`, or `cout`) is based on using anonymous objects:

- First, a class is defined, e.g. `Align`, whose constructor expects the arguments configuring the required manipulation. In our example representing, respectively, a field width and an alignment type.
- The class also supports an overloaded insertion (or extraction) operator. E.g.,

          ostream &operator<<(ostream &ostr, Align const &align)

- Next, the (anonymous) object is inserted into a stream. The insertion operator passes the stream to `Align::align`, allowing that member to configure (and return) the provided stream.

Here is an example of a little program using such a home-made manipulator expecting multiple arguments:

        #include <iostream>
        #include <iomanip>

        class Align
        {
            unsigned d_width;
            std::ios::fmtflags d_alignment;

            public:
                Align(unsigned width, std::ios::fmtflags alignment);
                std::ostream &operator()(std::ostream &ostr) const;
        };

        Align::Align(unsigned width, std::ios::fmtflags alignment)
        :
            d_width(width),
            d_alignment(alignment)
        {}

        std::ostream &Align::operator()(std::ostream &ostr) const
        {
            ostr.setf(d_alignment, std::ios::adjustfield);
            return ostr << std::setw(d_width);
        }

        std::ostream &operator<<(std::ostream &ostr, Align &&align)
        {
            return align(ostr);
        }

        using namespace std;

        int main()
        {
            cout
                << "`" << Align{ 5, ios::left } << "hi" << "'"
                << "`" << Align{ 10, ios::right } << "there" << "'\n";
        }

        /*
            Generated output:

            `hi   '`     there'
        */

When (local) objects must be manipulated, then the class that must provide manipulators may define function call operators receiving the required arguments. E.g., consider a class `Matrix` that should allow its users to specify the value and line separators when inserting the matrix into an `ostream`.

Two data members (e.g., `char const *d_valueSep` and `char const *d_lineSep`) are defined (and initialized to acceptable values). The insertion function inserts `d_valueSep` between values, and `d_lineSep` at the end of inserted rows. The member `operator()(char const *valueSep, char const *lineSep)` simply assigns values to the corresponding data members.

Given an object `Matrix matrix`, then at this point `matrix(" ", "\n")` can be called. The function call operator should probably not insert the matrix, as the responsibility of manipulators is to manipulate, not to insert. So, to insert a matrix a statement like

            cout << matrix(" ", "\n") << matrix << '\n';

should probably be used. The manipulator (i.e., function call operator) assigns the proper values to `d_valueSep` and `d_lineSep`, which are then used during the actual insertion.

The return value of the function call operator remains to be specified. The return value should be insertable, but in fact should not insert anything at all. An empty NTBS could be returned, but that's a bit kludge-like. Instead the address of a manipulator function, not performing any action, can be returned. Here's the implementation of such an empty manipulator:

            // static       (alternatively a free function could be used)
            std::ostream &Matrix::nop(std::ostream &out)
            {
                return out;
            }

Thus, the implementation of the `Matrix's` manipulator becomes:

            std::ostream &(
                *Matrix::operator()(char const *valueSep, char const *lineSep) )
                                                                (std::ostream &)
            {
                d_valueSep = valueSep;
                d_lineSep = lineSep;
                return nop;
            }

Instead (probably a matter of taste) of returning the address of an empty function the manipulator could first set the required insertion-specific values and could then return itself: the `Matrix` would be inserted according to the just assigned values to the insertion variables:

            Matrix const &Matrix::operator()
                (char const *valueSep, char const *lineSep)
            {
                d_valueSep = valueSep;
                d_lineSep = lineSep;
                return *this;
            }

In this case the insertion statement is simplified to

        cout << matrix(" ", "\n") << '\n';

## 11.12: Lambda expressions

C++ supports lambda expressions. As we'll see in chapter 19 generic algorithms often accept arguments that can either be function objects or plain functions. Examples are the `sort` (cf. section 19.1.54) and `find_if` (cf. section 19.1.15) generic algorithms. As a rule of thumb: when a called function must remember its state a function object is appropriate, otherwise a plain function can be used.

Frequently the function or function object is not readily available, and it must be defined in or near the location where it is used. This is commonly realized by defining a class or function in the anonymous namespace (say: class or function A), passing an A to the code needing A. If that code is itself a member function of the class B, then A's implementation might benefit from having access to the members of class B.

This scheme usually results in a significant amount of code (defining the class), or it results in complex code (to make available software elements that aren't automatically accessible to A's code). It may also result in code that is irrelevant at the current level of specification. Nested classes don't solve these problems either. Moreover, nested classes can't be used in templates.

lambda expressions solve these problems. A lambda expression defines an anonymous function object which may immediately be passed to functions expecting function object arguments, as explained in the following sections.

According to the C++ standard, lambda expressions provide a concise way to create simple function objects. The emphasis here is on simple: a lambda expression's size should be comparable to the size of inline-functions: just one or maybe two statements. If you need more code, then encapsulate that code in a separate function which is then called from inside the lambda expression's compound statement, or consider designing a separate function object.

### 11.12.1: Lambda expressions: syntax

A lambda expression defines an anonymous function object, also called a closure object or simply a closure.

When a lambda expression is evaluated it results in a temporary function object (the closure object). This temporary function object is of a unique anonymous class type, called its closure type.

Lambda expressions are used inside blocks, classes or namespaces (i.e., pretty much anywhere you like). Their implied closure type is defined in the smallest block, class or namespace scope containing the lambda expression. The closure object's visibility starts at its point of definition and ends where its closure type ends (their visibility is identical to the visibility of plain variables).

The closure type defines a public inline const function call operator. Here is an example of a lambda expression:

        []                      // the `lambda-introducer'
        (int x, int y)          // the `lambda-declarator'
        {                       // the function's body
            return x * y;
        }

This function (formally: the function call operator of the closure type created by this lambda expression) expects two `int` arguments and returns their product. It is an inline `const` member of its closure type. The function's `const` attribute is removed if the lambda expression specifies `mutable`. E.g.,

        [](int x, int y) mutable
        ...

The lambda-declarator may be omitted if no parameters are defined, but when specifying `mutable` (or `constexpr`, see below) a lambda-declarator must be specified (at least by specifying an empty set of parentheses). The parameters in a lambda declarator cannot be given default arguments.

Lambda declarator specifiers can be specified as `mutable`, `constexpr`, or both. When specifying `constexpr` the lambda-expression is a `constexpr`, which may be compile-time evaluated if its arguments qualify as const-expressions. If a lambda-expression is defined inside a `constexpr` function then the lambda-expression itself automatically becomes a `constexpr` itself, and the `constexpr` lambda declarator specifier is not required. Thus, the following two function definitions are identical:

        int constexpr change10(int n)
        {
            return [n]
                   {
                       return n > 10 ? n - 10 : n + 10;
                   }();
        }

        int constexpr change10(int n)
        {
            return [n] () constexpr
                   {
                       return n > 10 ? n - 10 : n + 10;
                   }();
        }

The lambda expression defined at the top of this section could for example be used in combination with the `accumulate` generic algorithm (cf. section 19.1.2) to compute the product of a series of `int` values stored in a vector:

        cout << accumulate(vi.begin(), vi.end(), 1,
                    [] (int x, int y)
                    {
                        return x * y;
                    }
                );

This lambda expression implicitly defines its return type as `decltype(x * y)`. Implicit return types can be used in these cases:

- the lambda expression does not contain a `return` statement (i.e., it's a void lambda expression);
- the lambda expression contains a single `return` statement; or
- the lambda expression contains multiple `return` statements returning values of identical types (e.g., all `int` values).

If there are multiple `return` statements returning values of different types then the lambda expression's return type must explicitly be specified using a late-specified return type, (cf. section 3.3.7):

        [](bool neg, double y) -> int
        {
            return neg ? -y : y;
        }

Variables which are visible at the location of a lambda expression may be accessed by the lambda expression's compound statement. Which variables and how they are accessed depends on specifications in the lambda-introducer. In the following overview: when it's stated that `variables can be modified' then that only applies to variables that themselves allow modifications.

- Global variables are always accessible, and can be modified if their definitions allow modifications;
- If the lambda expression is defined inside a function then that function's local variables may be accessed by the lambda expression's compound statement if their names are listed inside the lambda-introducer.
  The specification `local` is used below as a shorthand for a (comma-separated) list of names of local variables of the surrounding function that are visible in the lambda expression's compound statement;
- Local variables specified in the lambda introducer are in fact data members of the lambda expression which are initialized by the corresponding local variables of the function surrounding the lambda expression. This is illustrated by the following example showing different addresses for `var` (however, copying can be prevented as covered below):

          #include <iostream>

          int main()
          {
              int var = 12;
              std::cout << &var << '\n';
              [var]               // lambda expr. using 'var'
              {
                  std::cout << &var << '\n';
              }();                // directly call the lambda expr.
          }

- When the lambda expression is defined inside a class member function the lambda-introducer may specify `this` or `*this` allowing the lambda function to access/use the class's members (not defining copies as when accessing local variables). When `this` is specified the class's members can be accessed and the class's (non-const) data members can be modified. When `*this` is specified the lambda expression uses a copy of the class's object.

By default lambda expressions define constant (immutable) function objects, but by appending `mutable` to the lambda declarator they are defined as mutable function objects. Sometimes using `mutable` or not is irrelevant. In those cases ``mutable_opt`' is specified below. If `mutable_opt` is not specified then specifying `mutable` indicates that the lambda expression's function isn't a `const` member function anymore, so it may modify its (modifiable) data members.

Below specifications `(...)` refer to the lambda expression's declarator, and lambda introducers ending in `, ...]` indicate that they may specify `, this` or `, *this`.
There is no required ordering of the `this, *this` and `local` specifications.

- `[...] (...) mutable_opt`: only global variables can be accessed;

- `[local, ...] (...)`: like the previous specification, with `local` being defined as the lambda expression's data member(s) initialized by copying the surrounding function's local variable(s). When `mutable` is specified the (copied) `local` variable(s) can be modified;

- `[&local, ...] (...)`: like the previous specification, but the local variable(s) specified using `&`-prefixes are available as references to the class's data members. They can be modified if those members are non-const;

- `[&d_local = std::as_const(local), ...] (...)` defines the lambda expression's `d_local` data member as a reference to the (immutable) `local` variable of the surrounding function. The `d_local` data members remains a reference to an immutable `local` variable whether or not `mutable` is specified.
  To use `std::as_const` the `<utility>` header file must be included;

- `[&, ...] (...) mutable_opt`: the `local reference specifier': local variables are visible as modifiable references. If some of those references should not be able to modify their local variables then use specifications like `&d_local = std::as_const(local)` for those variables.

- `[vars, ...] (...)`: in addition to the above specifications lambda expressions may define their own data members. E.g., to define a lambda expression having its own `int count` and `double value` data members, also allowing it to access the caller's local variables its lambda-introducers can be specified as `[&, count = int(0), value = double(0)]`.
  Such local variables are defined by specifying their names, followed by their type-specifying initializations;

- `[=, ...] (...)`: if the lambda introducer starts with `=` then all local variables are available as copies of the surrounding function's local variables;

- `[=, &local, ...]`: like the previous specification, but the local variable(s) prefixed by `&` are available as references. If those local variables are non-const they can be modified. If some of those references should not be able to modify their local variables then use specifications like `&d_local = std::as_const(local)`;

Even when not specified, lambda expressions defined inside class member functions implicitly capture their `this` pointers, and class members are always accessed relative to `this`.

When members are called asynchronously (cf. chapter 20) a problem may arise, because the asynchronously called lambda function may refer to members of an object whose lifetime ended shortly after asynchronously calling the lambda function. This potential problem is solved using ``*this`' in the lambda-introducer if it starts with `=` (e.g., `[=, *this]`). In this case when the object's scope ends it is not immediately destroyed, but its lifetime is extended for the duration of the lambda-expression's execution. Consider the following example:

        struct S2
        {
            double ohseven = .007;

            auto f()
            {
                return [this]                       // (1, see below)
                       {
                            return [*this]          // (2)
                                   {
                                        return ohseven; // OK
                                   };
                       }();                         // (3)
            }

            auto g()
            {
                return []
                       {
                            return [*this]
                            {
                                // error: *this not captured by
                                // the outer lambda-expression
                            };
                        }();
            }
        };

Although lambda expressions are anonymous function objects, they can be assigned to variables. Often, the variable is defined using the keyword `auto`. E.g.,

        auto sqr = [](int value)
                   {
                       return value * value;
                   };

The lifetime of such a lambda expression is equal to the lifetime of `sqr`, which is the variable receiving the lambda expression as its value.

Defining a lambda expression is different from calling its function operator. The function `S2::f()` returns what the lamba expression (1)'s function call operator returns: its function call operator is called by using `()` (at (3)). What it in fact returns is another anonymous function object (defined at `(2)`). As that's just a function object, to retrieve its value it must still be called from `f's` return value using something like this:

        S2 s2;
        s2.f()();

Here, the second set of parentheses activates the returned function object's function call operator. Had the parentheses been omitted at (3) then `S2::f()` would have returned a mere anonymous function object (defined at (1)), in which case it would require three sets of parentheses to retrieve `ohseven's` value: `s2.f()()()`.

### 11.12.2: Using lambda expressions

Now that the syntax of lambda expressions have been covered let's see how they can be used in various situations.

First we consider named lambda expressions. Named lambda expressions nicely fit in the niche of local functions: when a function needs to perform computations which are at a conceptually lower level than the function's task itself, then it's attractive to encapsulate these computations in a separate support function and call the support function where needed. Although support functions can be defined in anonymous namespaces, that quickly becomes awkward when the requiring function is a class member and the support function also must access the class's members.

In that case a named lambda expression can be used: it can be defined inside a requiring function, and it may be given full access to the surrounding class. The name to which the lambda expression is assigned becomes the name of a function which can be called from the surrounding function. Here is an example, converting a numeric IP address to a dotted decimal string, which can also be accessed directly from an `Dotted` object (all implementations in-class to conserve space):

        class Dotted
        {
            std::string d_dotted;

            public:
                std::string const &dotted() const
                {
                    return d_dotted;
                }
                std::string const &dotted(size_t ip)
                {
                    auto octet =
                        [](size_t idx, size_t numeric)
                        {
                            return to_string(numeric >> idx * 8 & 0xff);
                        };

                    d_dotted =
                            octet(3, ip) + '.' + octet(2, ip) + '.' +
                            octet(1, ip) + '.' + octet(0, ip);

                    return d_dotted;
                }
        };

Next we consider the use of generic algorithms, like the `for_each` (cf. section 19.1.18):

        void showSum(vector<int> const &vi)
        {
            int total = 0;
            for_each(
                vi.begin(), vi.end(),
                [&](int x)
                {
                    total += x;
                }
            );
            std::cout << total << '\n';
        }

Here the variable `int total` is passed to the lambda expression by reference and is directly accessed by the function. Its parameter list merely defines an `int x`, which is initialized in sequence by each of the values stored in `vi`. Once the generic algorithm has completed `showSum`'s variable `total` has received a value that is equal to the sum of all the vector's values. It has outlived the lambda expression and its value is displayed.

But although generic algorithms are extremely useful, there may not always be one that fits the task at hand. Furthermore, an algorithm like `for_each` looks a bit unwieldy, now that the language offers range-based for-loops. So let's try this, instead of the above implementation:

        void showSum(vector<int> const &vi)
        {
            int total = 0;
            for (auto el: vi)
                [&](int x)
                {
                    total += x;
                };

            std::cout << total << '\n';
        }

But when `showSum` is now called, its `cout` statement consistently reports 0. What's happening here?

When a generic algorithm is given a lambda function, its implementation instantiates a reference to a function. The referenced function is thereupon called from within the generic algorithm. But, in the above example the range-based for-loop's nested statement merely represents the definition of a lambda function. Nothing is actually called, and hence `total` remains equal to 0.

Thus, to make the above example work we not only must define the lambda expression, but we must also call the lambda function. We can do this by giving the lambda function a name, and then call the lambda function by its given name:

        void showSum(vector<int> const &vi)
        {
            int total = 0;
            for (auto el: vi)
            {
                auto lambda = [&](int x)
                                {
                                    total += x;
                                };

                lambda(el);
            }
            std::cout << total << '\n';
        }

In fact, there is no need to give the lambda function a name: the `auto lambda` definition represents the lambda function, which could also directly be called. The syntax for doing this may look a bit weird, but there's nothing wrong with it, and it allows us to drop the compound statement, required in the last example, completely. Here goes:

        void showSum(vector<int> const &vi)
        {
            int total = 0;
            for (auto el: vi)
                [&](int x)
                {
                    total += x;
                }(el);          // immediately append the
                                // argument list to the lambda
                                // function's definition
            std::cout << total << '\n';
        }

Lambda expressions can also be used to prevent spurious returns from `condition_variable's wait` calls (cf. section 20.4.3).

The class `condition_variable` allows us to do so by offering `wait` members expecting a lock and a predicate. The predicate checks the data's state, and returns `true` if the data's state allows the data's processing. Here is an alternative implementation of the `down` member shown in section 20.4.3, checking for the data's actual availability:

        void down()
        {
            unique_lock<mutex> lock(sem_mutex);
            condition.wait(lock,
                [&]()
                {
                    return semaphore != 0
                }
            );
            --semaphore;
        }

The lambda expression ensures that `wait` only returns once `semaphore` has been incremented.

Lambda expression are primarily used to obtain functors that are used in a very localized section of a program. Since they are used inside an existing function we should realize that once we use lambda functions multiple aggregation levels are mixed. Normally a function implements a task which can be described at its own aggregation level using just a few sentences. E.g., ``the function `std::sort` sorts a data structure by comparing its elements in a way that is appropriate to the context where `sort` is called''. By using an existing comparison method the aggregation level is kept, and the statement is clear by itself. E.g.,

        sort(data.begin(), data.end(), greater<DataType>());

If an existing comparison method is not available, a tailor-made function object must be created. This could be realized using a lambda expression. E.g.,

        sort(data.begin(), data.end(),
            [&](DataType const &lhs, DataType const &rhs)
            {
                return lhs.greater(rhs);
            }
        );

Looking at the latter example, we should realize that here two different aggregation levels are mixed: at the top level the intent is to sort the elements in `data`, but at the nested level (inside the lambda expression) something completely different happens. Inside the lambda expression we define how a the decision is made about which of the two objects is the greater. Code exhibiting such mixed aggregation levels is hard to read, and should be avoided.

On the other hand: lambda expressions also simplify code because the overhead of defining tailor-made functors is avoided. The advice, therefore, is to use lambda expressions sparingly. When they are used make sure that their sizes remain small. As a rule of thumb: lambda expressions should be treated like in-line functions, and should merely consist of one, or maybe occasionally two expressions.

A special group of lambda expressions is known as generic lambda expressions. As generic lambda expressions are in fact class templates, their coverage is postponed until chapter 22.

## 11.13: The case of [io]fstream::open()

Earlier, in section 6.4.2.1, it was noted that the `[io]fstream::open` members expect an `ios::openmode` value as their final argument. E.g., to open an `fstream` object for writing you could do as follows:

        fstream out;
        out.open("/tmp/out", ios::out);

Combinations are also possible. To open an `fstream` object for both reading and writing the following stanza is often seen:

        fstream out;
        out.open("/tmp/out", ios::in | ios::out);

When trying to combine enum values using a `home made' `enum` we may run into problems. Consider the following:

        enum Permission
        {
            READ =      1 << 0,
            WRITE =     1 << 1,
            EXECUTE =   1 << 2
        };

        void setPermission(Permission permission);

        int main()
        {
            setPermission(READ | WRITE);
        }

When offering this little program to the compiler it replies with an error message like this:

`invalid conversion from 'int' to 'Permission'`

The question is of course: why is it OK to combine `ios::openmode` values passing these combined values to the stream's `open` member, but not OK to combine `Permission` values.

Combining enum values using arithmetic operators results in `int`-typed values. Conceptually this never was our intention. Conceptually it can be considered correct to combine enum values if the resulting value conceptually makes sense as a value that is still within the original enumeration domain. Note that after adding a value `READWRITE = READ | WRITE` to the above `enum` we're still not allowed to specify `READ | WRITE` as an argument to `setPermission`.

To answer the question about combining enumeration values and yet stay within the enumeration's domain we turn to operator overloading. Up to this point operator overloading has been applied to class types. Free functions like `operator<<` have been overloaded, and those overloads are conceptually within the domain of their class.

As C++ is a strongly typed language realize that defining an `enum` is really something beyond the mere association of `int`-values with symbolic names. An enumeration type is really a type of its own, and as with any type its operators can be overloaded. When writing `READ | WRITE` the compiler performs the default conversion from enum values to `int` values and applies the operator to `ints`. It does so when it has no alternative.

But it is also possible to overload the enum type's operators. Thus we may ensure that we'll remain within the enum's domain even though the resulting value wasn't defined by the enum. The advantage of type-safety and conceptual clarity is considered to outweigh the somewhat peculiar introduction of values hitherto not defined by the enum.

Here is an example of such an overloaded operator:

        Permission operator|(Permission left, Permission right)
        {
            return static_cast<Permission>(static_cast<int>(left) | right);
        }

Other operators can easily and analogously be constructed.

Operators like the above were defined for the `ios::openmode` enumeration type, allowing us to specify `ios::in | ios::out` as argument to `open` while specifying the corresponding parameter as `ios::openmode` as well. Clearly, operator overloading can be used in many situations, not necessarily only involving class-types.

## 11.14: User-defined literals

In addition to the well-known literals, like numerical constants (with or without suffixes), character constants and string (textual) literals, C++ also supports user-defined literals, also known as extensible literals.

A user-defined literal is defined by a function (see also section 23.3) that must be defined at namespace scope. Such a function is called a literal operator. A literal operator cannot be a class member function. The names of a literal operator must start with an underscore, and a literal operator is used (called) by suffixing its name (including the underscore) to the argument that must be passed to it . Assuming `_NM2km` (nautical mile to km) is the name of a literal operator, then it could be called as `100_NM2km`, producing, e.g., the value 185.2.

Using `Type` to represent the return type of the literal operator its generic declaration looks like this:

        Type operator "" _identifier(parameter-list);

The blank space trailing the empty string is required. The parameter lists of literal operators can be:

- `unsigned long long int`. It is used as, e.g., `123_identifier`. The argument to this literal operator can be decimal constants, binary constants (initial 0b), octal constants (initial 0) and hexadecimal constants (initial 0x);
- `long double`. It is used as, e.g., `12.25_NM2km`;
- `char const *text`. The `text` argument is an NTBS. It is used as, e.g., `1234_pental`. The argument must not be given double quotes, and must represent a numeric constant, as also expected by literal operators defining `unsigned long long int` parameters.
- `char const *text, size_t len`. Here, the compiler determines `len` as if it had called `strlen(text)`. It is used as, e.g., `"hello"_nVowels`;
- `wchar_t const *text, size_t len`, same as the previous one, but accepting a string of `wchar_t` characters. It is used as, e.g., `L"1234"_charSum`;
- `char16_t const *text, size_t len`, same as the previous one, but accepting a string of `char16_t` characters. It is used as, e.g., `u"utf 16"_uc`;
- `char32_t const *text, size_t len`, same as the previous one, but accepting a string of `char32_t` characters. It is used as, e.g., `U"UTF 32"_lc`;

If literal operators are overloaded the compiler will pick the literal operator requiring the least `effort'. E.g., 120 is processed by a literal operator defining an `unsigned long long int` parameter and not by its overloaded version, defining a `char const *` parameter. But if overloaded literal operators exist defining `char const *` and `long double` parameters then the operator defining a `char const *` parameter is used when the argument 120 is provided, while the operator defining a `long double` parameter is used with the argument 120.3.

A literator operator can define any return type. Here is an example of a definition of the `_NM2km` literal operator:

        double operator "" _NM2km(char const *nm)
        {
            return std::stod(nm) * 1.852;
        }

        double value = 120_NM2km;   // example of use

Of course, the argument could also have been a `long double` constant. Here's an alternative implementation, explicitly expecting a `long double`:

        double constexpr operator "" _NM2km(long double nm)
        {
            return nm * 1.852;
        }

        double value = 450.5_NM2km;   // example of use

A numeric constant can also be processed completely at compile-time. Section 23.3 provides the details of this type of literal operator.

Arguments to literal operators are themselves always constants. A literal operator like `_NM2km` cannot be used to convert, e.g., the value of a variable. A literal operator, although it is defined as a function, cannot be called like a function. The following examples therefore result in compilation errors:

        double speed;

        speed_NM2km;        // no identifier 'speed_NM2km'
        _NM2km(speed);      // no function _NM2km
        _NM2km(120.3);      // no function _NM2km

## 11.15: Overloadable operators

The following operators can be overloaded:

        +       -       *       /       %       ^       &       |
        ~       !       ,       =       <=>     <       >       <=
        >=      ++      --      <<      >>      ==      !=      &&
        ||      +=      -=      *=      /=      %=      ^=      &=
        |=      <<=     >>=     []      ()      ->      ->*     new
        new[]   delete  delete[]

Several operators have textual alternatives:

textual alternative | operator

`and` | `&&`
`and_eq` | `&=`
`bitand` | `&`
`bitor` | `|`
`compl` | `~`
`not` | `!`
`not_eq` | `!=`
`or` | `||`
`or_eq` | `|=`
`xor` | `^`
`xor_eq` | `^=`

`Textual' alternatives of operators are also overloadable (e.g., `operator and`). However, note that textual alternatives are not additional operators. So, within the same context `operator&&` and `operator and` can not both be overloaded.

Several of these operators may only be overloaded as member functions within a class. This holds true for the `'='`, the `'[]'`, the `'()'` and the `'->'` operators. Consequently, it isn't possible to redefine, e.g., the assignment operator globally in such a way that it accepts a `char const *` as an `lvalue` and a `String &` as an rvalue. Fortunately, that isn't necessary either, as we have seen in section 11.3.

Finally, the following operators cannot be overloaded:

        .       .*      ::      ?:      sizeof  typeid

- Table of Contents
- Previous Chapter
- Next Chapter