- Next chapter
- Previous chapter
- Table of contents

# Chapter 6: More About Operator Overloading

> We're always interested in getting feedback. E-mail us if you like this guide, if you think that important material is omitted, if you encounter errors in the code examples or in the documentation, if you find any typos, or generally just if you feel like e-mailing. Mail to Frank Brokken or use an e-mail form. Please state the concerned document version, found in the title.

Now that we've covered the overloaded assignment operator in depth, and now that we've seen some examples of other overloaded operators as well (i.e., the insertion and extraction operators), let's take a look at some other interesting examples of operator overloading.

## 6.1: Overloading operator[]()

As our next example of operator overloading, we present a class which is meant to operate on an array of `int`s. Indexing the array elements occurs with the standard array operator `[]`, but additionally the class checks for boundary overflow. Furthermore, the array operator is interesting in that it both produces a value and accepts a value, when used, respectively, as a right-hand value and a left-hand value in expressions.

An example of the use of the class is given here:

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

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

                                    // produces boundary
                                    // overflow
            for (int i = 0; i <= 20; i++)
                cout << "At index " << i << ": value is " << x[i] << endl;

            return (0);
        }

This example shows how an array is created to contain 20 `int`s. The elements of the array can be assigned or retrieved. The above example should produce a run-time error, generated by the class `IntArray`: the last `for` loop causing a boundary overflow, since `x[20]` is addressed while legal indices range from 0 to 19, inclusive.

We give the following class interface:

        class IntArray
        {
             public:
                IntArray(int size = 1);     // default size: 1 int
                IntArray(IntArray const &other);
                ~IntArray();
                IntArray const &operator=(IntArray const &other);

                                // overloaded index operators:
                int &operator[](int index);         // first
                int operator[](int index) const;    // second
            private:
                void boundary(int index) const;
                void destroy();             // standard functions
                                            // used to copy/destroy
                void copy(IntArray const &other);

                int
                    *data,
                    size;
        };

        #include <iostream>

Concerning this class interface we remark:

- The class has a constructor with a default `int` argument, specifying the array size. This function serves also as the default constructor, since the compiler will substitute 1 for the argument when none is given.

- The class internally uses a pointer to reach allocated memory. Hence, the necessary tools are provided: a copy constructor, an overloaded assignment function and a destructor.

- Note that there are two overloaded index operators. Why are there two of them ?

  The first overloaded index operator allows us to reach and obtain the elements of the `IntArray` object.

  This overloaded operator has as its prototype a function that returns a reference to an `int`. This allows us to use expressions like `x[10]` on the left-hand side and on the right-hand side of an assignment.

  We can therefore use the same function to retrieve and to assign values. Furthermore note that the returnvalue of the overloaded array operator is not an `int const &`, but rather an `int &`. In this situation we don't want the `const`, as we must be able to change the element we want to access, if the operator is used as a left-hand value in an assignment.

  However, 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 a const object, which cannot be modified. The compiler detects this and will refuse to compile this object definition if only the first overloaded index operator is available. Hence the second overloaded index operator. Here the return-value is an `int`, rather than an `int &`, and the member-function itself is a `const` member function. This second form of the overloaded index operator cannot be used with non-`const` objects, but it's perfect for `const` objects. It can only be used for value-retrieval, not for value-assignment, but that is precisely what we want with `const` objects.

- We used the standard implementations of the copy constructor, the overloaded assignment operator and the destructor, discussed before (in section 5.4.1), albeit that we've left out the implementation of the function `destroy()`, as this function would consist of merely one statement (`delete data`).

- As the elements of `data` are `int`s, no `delete []` is needed. It does no harm, either. Therefore, since we use the `[]` when the object is created, we also use the `[]` when the data are eventually destroyed.

The member functions of the class are presented next.

        #include "intarray.h"

        IntArray::IntArray(int sz)
        {
            if (sz < 1)
            {
                cerr << "IntArray: size of array must be >= 1, not " << sz
                     << "!" << endl;
                exit(1);
            }
            // remember size, create array
            size = sz;
            data = new int [sz];
        }

        // copy constructor
        IntArray::IntArray(IntArray const &other)
        {
            copy(other);
        }

        // destructor
        IntArray::~IntArray()
        {
            delete [] data;
        }

        // overloaded assignment
        IntArray const &IntArray::operator=(IntArray const &other)
        {
            // take action only when no auto-assignment
            if (this != &other)
            {
                delete [] data;
                copy(other);
            }
            return (*this);
        }

        // copy() primitive
        void IntArray::copy(IntArray const &other)
        {
            // set size
            size = other.size;

            // create array
            data = new int [size];

            // copy other's values
            for (register int i = 0; i < size; i++)
                data[i] = other.data[i];
        }

        // here is the first overloaded array operator
        int &IntArray::operator[](int index)
        {
            boundary(index);
            return (data[index]);   // emit the reference
        }

        // and the second overloaded array operator
        int IntArray::operator[](int index) const
        {
            boundary(index);
            return (data[index]);   // emit the value
        }

        // the function checking the boundaries for the index:
        void IntArray::boundary(int index) const
        {
            // check for array boundary over/underflow
            if (index < 0 || index >= size)
            {
                cerr << "IntArray: boundary overflow or underflow, index = "
                     << index << ", should range from 0 to " << size - 1 << endl;
                exit(1);
            }
        }

## 6.2: Overloading operator new(size_t)

If the `operator new` is overloaded, it must have a `void *` return type, and at least an argument of type `size_t`. The `size_t` type is defined in `stddef.h`, which must therefore be included when the operator `new` is overloaded.

It is also possible to define multiple versions of the `operator new`, as long as each version has its own unique set of arguments. The global `new` operator can still be used, through the `::`-operator. If a class `X` overloads the operator `new`, then the system-provided operator `new` is activated by

`X *x = ::new X();`

Furthermore, the `new []` construction will always use the default operator `new`.

An example of the overloaded operator `new` for the class `X` is the following:

        #include <stddef.h>

        void *X::operator new(size_t sizeofX)
        {
            void
                *p = new char[sizeofX];

            return (memset(p, 0, sizeof(X)));
        }

Now, let's see what happens when the operator `new` is defined for the `class X`. Assume that class is defined as follows (For the sake of simplicity we have violated the principle of encapsulation here. The principle of encapsulation, however, is immaterial to the discussion of the workings of the operator `new`.):

        class X
        {
            public:
                void *operator new(size_t sizeofX);

                int
                    x,
                    y,
                    z;
        };

Now, consider the following program fragment:

        #include "X.h"  // class X interface etc.

        int main()
        {
            X
                *x = new X();

            cout << x->x << ", " << x->y << ", "<< x->z << endl;
            return (0);
        }

This small program produces the following output:
`0, 0, 0`

Our little program performed the following actions:

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

Due to the initialization of the block of memory by the `new` operator the allocated `X` object was already initialized to zeros when the constructor was called.

Non-static object member functions are passed a (hidden) pointer to the object on which they should operate. This hidden pointer becomes the `this` pointer inside the memberfunction. This procedure is also followed by the constructor. In the following fragments of pseudo C++ the pointer is made visible. In the first part an `X` object is declared directly, in the second part of the example the (overloaded) operator `new` is used:

            X::X(&x);   // x's address is passed to the constructor
                        // the compiler made 'x' available

            void        // ask new to allocate the memory for an X
                *ptr = X::operator new();
            X::X(ptr);  // and let the constructor operate on the
                        // memory returned by 'operator new'

Notice that in the pseudo `C++` fragment the member functions were treated as static functions of the class `X`. Actually, the `operator new()` operator is a static functions of its class: it cannot reach data members of its object, since it's normally the task of the `operator new()` to create room for that object first. It can do that by allocating enough memory, and by initializing the area as required. Next, the memory is passed over to the constructor (as the `this` pointer) for further processing. The fact that an overloaded operator `new` is in fact a static function, not requiring an object of its class can be illustrated in the following (frowned upon in normal situations!) program fragment, which can be compiled without problems (assume `class X` has been defined and is available as before):

        int main()
        {
            X
                x;

            X::operator new(sizeof x);

            return (0);
        }

The call to `X::operator new()` returns a `void *` to an initialized block of memory, the size of an `X` object.

The operator `new` can have multiple parameters. The first parameter again is the `size_t` parameter, other parameters must be passed during the call to the `operator new`. For example:

        class X
        {
            public:
                void *operator new(size_t p1, unsigned p2);
                void *operator new(size_t p1, char const *fmt, ...);
        };

        int main()
        {
            X
                *object1 = new(12) X(),
                *object2 = new("%d %d", 12, 13) X(),
                *object3 = new("%d", 12) X();

            return (0);
        }

The object (object1) is a pointer to an `X` object for which the memory has been allocated by the call to the first overloaded `operator new`, followed by the call of the constructor `X()` for that block of memory. The object (object2) is a pointer to an `X` object for which the memory has been allocated by the call to the second overloaded `operator new`, followed again by a call of the constructor `X()` for its block of memory. Notice that `object3` also uses the second overloaded `operator new()`: that overloaded operator accepts a variable number of arguments, the first of which is a `char const *`.

## 6.3: Overloading operator delete(void *)

The `delete` operator may be overloaded too. The `operator delete` must have a `void *` argument, and an optional second argument of type `size_t`, which is the size in bytes of objects of the class for which the `operator delete` is overloaded. The returntype of the overloaded `operator delete` is void.

Therefore, in a class the operator `delete` may be overloaded using the following prototype:

`void operator delete(void *);`

or

`void operator delete(void *, size_t);`

The `home-made' `delete` operator is called after executing the class' destructor. So, the statement

`delete ptr;`

with `ptr` being a pointer to an object of the class `X` for which the operator `delete` was overloaded, boils down to the following statements:

        X::~X(ptr);     // call the destructor function itself

                        // and do things with the memory pointed
                        // to by ptr itself.
        X::operator delete(ptr, sizeof(*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 activated using the `::` scope resolution operator. For example:

        void X::operator delete(void *ptr)
        {
            // ... whatever else is considered necessary

            // use the default operator delete
            ::delete ptr;
        }

## 6.4: Cin, cout, cerr and their operators

This section describes how a class can be adapted in such a way that it can be used with the `C++` streams `cout` and `cerr` and the insertion operator `<<`. Adaptating a class in such a way that the `istream`'s extraction operator `>>` can be used occurs in a similar way and is not further illustrated here.

The implementation of an overloaded operator `<<` in the context of `cout` or `cerr` involves the base class of `cout` or `cerr`, which is `ostream`. This class is declared in the header file `iostream` and defines only overloaded operator functions for `basic' types, such as, `int`, `char*`, etc.. The purpose of this section is to show how an operator function can be defined which processes a new class, say `Person` (see chapter 5.1) , so that constructions as the following one become possible:

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

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

The statement `cout << kr` involves the operator `<<` and its two operands: an `ostream &` and a `Person &`. The proposed action is defined in a class-less operator function `operator<<()` expecting two arguments:

        // declaration in, say, person.h
        ostream &operator<<(ostream &, Person const &);

        // definition in some source file
        ostream &operator<<(ostream &stream, Person const &pers)
        {
            return
            (
                stream << "Name:    " << pers.getname()
                       << "Address: " << pers.getaddress()
                       << "Phone:   " << pers.getphone()
            );
        }

Concerning this function we remark the following:

- The function must return a (reference to) `ostream` object, to enable `chaining' of the operator.

- The two operands of the operator `<<` are stated as the two arguments of the overloading function.

- The class `ostream` provides the member function `opfx()`, which flushes any other `ostream` streams tied with the current stream. `opfx()` returns 0 when an error has been encountered (Cf. chapter 11).

  An improved form of the above function would therefore be:

          ostream &operator<<(ostream &stream, Person const &pers)
          {
              if (! stream.opfx())
                  return (stream);
              ...
          }

## 6.5: Conversion operators

A class may be constructed around a basic type. E.g., it is often fruitful to define a class `String` around the `char *`. Such a class may define all kinds of operations, like assignments. Take a look at the following class interface:

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

Objects from 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 assingment from a `char const *` also includes 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 `char const *String::getstr() const`. However, in the current context that looks a bit awkward, but it also doesn't seem to be the right way to go when an array of strings is defined, e.g., in a class `StringArray`, in which the `operator[]` is implemented to allow the access of individual strings. Take a look at the following class interface:

    class StringArray
    {
        public:
            StringArray(unsigned size);
            StringArray(StringArray const &other);
            StringArray const &operator=(StringArray const &rvalue);
            ~StringArray();

            String &operator[](unsigned index);
        private:
            String
                *store;
            unsigned
                n;
    };

The `StringArray` class has one interesting memberfunction: the overloaded array operator `operator[]`. It returns a `String` reference.

Using this operator assignments between the `String` elements can be realized:

        StringArray
            sa(10);

        ... // assume the array is filled here

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

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

`sa[3] = "hello world";`
When this is evaluated, the following steps are followed:

- 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]` can receive 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]`? We try the following code:

        char const
            *cp;

        cp = sa[3];

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

The naive solution is to resort to the accessor member function `getstr()`:

`cp = sa[3].getstr();`
That solution would work, but it looks so 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. Using a conversion operator a `String` object may be interpreted as a `char const *`, which can then be assigned to another `char const *`. Conversion operators can be implemented for all types for which a conversion is needed.

In the current example, the `class String` would need a conversion operator for a `char const *`. The general form of a conversion operator in the class interface is:

`operator <type>();`
With our `String` class, it would therefore be:
`operator char const *();`

The implementation of the conversion operator is straightforward:

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

Notes:

- There is no mentioning of a return type. The conversion operator has the type of the returned value just after the `operator` keyword.
- In certain situations the compiler needs a hand to disambiguate our intentions. In a statement like
  `printf("%s", sa[3]);`
  the compiler is confused: are we going to pass a `String &` or a `char const *` to the `printf()` function? To help the compiler out, we supply an explicit cast here:
  `printf("%s", static_cast<char const *>(sa[3]));`

For completion, the final `String` class interface, containing the conversion operator, looks like this:

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

## 6.6: The `explicit' keyword

Assume we have a class that's doing all kinds of interesting stuff. Its public members could be, e.g.:

        class Convertor
        {
            public:
                Convertor();
                Convertor(char const *str);
                Convertor(Convertor const &other);
                ~Convertor();
                operator char const*();
                void anyOtherMemberFunction();
        };

Objects of the class `Convertor` may be constructed using a default constructor and using a `char const *`. Functions might return `Convertor` objects and functions might expect `Convertor` objects as arguments. E.g.,

        Convertor returnConvertorObject()
        {
            Convertor
                convertor;

            return (convertor);
        }
        void expectConvertorObject(Convertor const &object)
        {
            ...
        }

In cases like these, implicit conversions to `Convertor` objects will be performed if there are constructors having one parameter (or multiple parameters, using default argument values), if an argument of the type of the single parameter is passed to or returned from the function. E.g., the following function expects a `char const *` and returns an `Convertor object` due to the implicit conversion from `char const *` to `Convertor` using the `Convertor(char const *)` constructor as middleman:

        Convertor returnConvertorObject(char const *str)
        {
            return (str);
        }

This conversion generally occurs wherever possible, and acts like some sort of `reversed' conversion operator: in applicable situations the constructor expecting one argument will be used if the argument is specified, and the class object is required.

If such implicit use of a constructor is not appropriate, it can be prevented by using the `explicit` modifier with the constructor. Constructors using the `explicit` modifier can only be used for the explicit definition of objects, and cannot be used as implicit type convertors anymore. For example, to prevent the implicit conversion from `char const *` to `Convertor` the class interface of the class `Convertor` must contain the constructor

        explicit Convertor(char const *str);

## 6.7: Overloading the increment and decrement operators

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

Suppose we define a class `bvector` whose members can be used to visit the elements of an array. The `bvector` object will return a pointer to an element of the array, and the increment operators will change the pointer to the next element. A partially defined `bvector` class is:

        class bvector
        {
            public:
                bvector(int *vector, unsigned size)
                :
                    vector(vector),
                    current(vector),
                    finish(vector + size)
                {}
                int *begin()
                {
                    return(current = vector);
                }
                operator int *() const
                {
                    return (current);
                }
                // increment and decrement operators: see the text
            private:
                int
                    *vector,
                    *current,
                    *finish;
        };

In order to privide this class with an overloaded increment operator, the following overloaded `operator++()` can be designed:

        int *bvector::operator++()
        {
            return (++current);
        }

As `current` is incremented before it is returned, the above overloaded `operator++()` clearly behaves like the prefix operator. However, it is not possible to use the same function to implement the postfix operator, as overloaded functions must differ in their parameterlists. To solve this problem, the convention is adopted to provide the postfix operator with an anonymous `int` parameter. So, the postfix increment operator can be designed as follows:

        int *bvector::operator++(int)
        {
            return (current++);
        }

In situations where the function `operator++()` is called explicitly, a dummy `int` argument may be passed to the function to indicate that the postfix version is required. If no argument is provided, the prefix version of the operator is used. E.g.,

        bvector
            *bvp = new bvector(intArray, 10);

        bvp->operator++(1); // postfix operator++()
        bvp->operator++()   // prefix operator++()

## 6.8: Function Objects

Function Objects are created by overloading the function call operator `operator()`. By defining the function call operator an object may be used as a function, hence the term function objects.

Function objects play an important role in the generic algorithms and they can be used profitably as alternatives to using pointers to functions. The fact that they are important in the context of the generic algorithms constitutes some sort of a didactical dilemma: at this point it would have been nice if the generic algorithms would have been covered, but for the discussion of the generic algorithms knowledge of function objects is an advantage. This bootstrap problem is solved in a well known way: by ignoring the dependency.

Function objects are `class type` objects for which the `operator()` has been defined. Usually they are used in combination with the generic algorithms, but they are also used in situations where otherwise pointers to functions would have been used. Another reason for using function objects is to support `inline` functions, something that is not possible via the pointers to functions construction.

Assume we have a class `Person` and an array of `Person` objects. 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 lineair search in an array. A program fragment in which this function is used is, e.g.,

            Person
                *pArray;
            unsigned
                n;

            n = fillPerson(&pArray);

            Person
                target(...);

            cout <<
                "The target person is " <<
                (
                    lsearch(&target, pArray, &n, sizeof(Person), compareFunction) ?
                        "found"
                    :
                        "not found"
                ) <<
                endl;

The function `fillPerson()` is called to fill the array, the target person is defined, and then `lsearch()` is used to locate the target person. The comparison function must be available, as its address is passed over to the function. It could be something like:

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

This, of course, assumes that the `operator!=()` has been overloaded in the class `Person`, as it is quite unlikely that a bytewise comparison will be appropriate here. But overloading `operator!=()` is no big deal, so let's assume that operator is available as well. In this situation an inline compare function cannot be used: as the address of the `compare()` function must be known to the `lsearch()` function. So, on the average `n / 2` times at least the following actions take place:

- The two arguments of the comparefunction are pushed on the stack,
- The final parameter of `lsearch()` is evaluated, producing the address of `compareFunction()`,
- The comparefunction is called,
- The address of the right-hand argument of the `Person::operator!=()`) argument is pushed on the stack,
- The `operator!=()` function is evaluated,
- The argument of `Person::operator!=()`) argument is popped off the stack,
- The two arguments of the comparefunction are popped off the stack.

When using function objects a different picture emerges. Assume we have constructed a function `PersonSearch()`, having the following prototype (realize that this is not the real thing. Normally a generic algorithm will be used instead of a home-made function. But for now our `PersonSearch()` function is used for the sake of argument):

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

The next program fragment shows the use of this function:

            Person
                *pArray;
            unsigned
                n;

            n = fillPerson(&pArray);

            cout <<
                "The target person is " <<
                (
                    PersonSearch(pArray, n, Person(...)) ?
                        "found"
                    :
                        "not found"
                ) <<
                endl;

Here we see that the target person is passed over to the function using an anonymous `Person` object. A named object could have been used as well, though. What happens inside `PersonSearch()` is shown next:

            Person const *PersonSearch(Person *base, size_t nmemb,
                                        Person const &target)
            {
                for (int idx = 0; idx < nmemb; ++idx)
                    if (!target(base[idx]))     // using the same returnvalues
                        return (base + idx);    // as lsearch(): 0 means 'found'
                return (0);
            }

The expression `target(base[idx])` shows our `target` object being used as a function object. Its implementation can be something like:

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

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

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

Now, `Person::operator()` is a simple function. It contains but one statement, and we could consider making it inline. Assuming we do so, here is what happens when the `operator()` is called:

- The address of the right-hand argument of the `Person::operator!=()`) argument is pushed on the stack,
- The `operator!=()` function is evaluated,
- The argument of `Person::operator!=()`) argument is popped off the stack,

Note that due to the fact that `operator()` is an inline function, it is not actually called. Instead `operator!=()` is called immediately. Also note that the required stack operations are fairly modest.

The `operator()` could have been avoided altogether in the above example. However, in the coming sections several predefined function objects are introduced calling specific operators of underlying datatypes. Usually these function object will receive one or two arguments (for, respectively, unary and binary operators).

Function objects play important roles in combination with generic algorithms. For example, there exists a generic algorithm `sort` that takes two iterators defining the range of objects that should be sorted, and a function object calling the appropriate comparison operator for two objects. Let's take a quick look at this situation. Assume strings are stored in a vector, and we want to sort the vector in descending order. In that case, sorting the vector `stringVec` is as simple as:

            sort(stringVec.begin(), stringVec.end(), greater<string>());

The last argument is in fact a constructor of the `greater` (template) class applied on `strings`. This object is called (as function object) by the `sort()` generic algorithm. The function object itself is not visible at this point: don't confuse the parentheses in `greater<string>()` with the calling of the function object. When the function object is actually called, it receives two arguments: two strings to compare for `greaterness'. Internally, the `operator>()` of the underlying datatype (i.e., `string`) is called to compare the two objects. Since the `greater::operator()` is defined inline, it is not actually present in the code. Rather, the `string::operator>()` is called by `sort()`.

Now that we know that a constructor is passed as argument to (many) generic algorithms, we can design our own function objects. Assume we want to sort our vector case-insensitively. How do we proceed? First we note that the default `string::operator<()` (for an incremental sort) is not appropriate, as it does case sensitive comparisons. So, we provide our own `case_less` class, in which the two strings are compared case-insensitively. Using the standard C function `strcasecmp()`, the following program performs the trick. It sorts in increasing order its command-line arguments:

    #include <iostream>
    #include <string>
    #include <functional>
    #include <algorithm>
    #include <string.h>

    class case_less
    {
        public:
            bool operator()(string const &left, string const &right) const
            {
                return (strcasecmp(left.c_str(), right.c_str()) < 0);
            }
    };

    int main(int argc, char **argv)
    {
        sort(argv, argv + argc, case_less());
        for (int idx = 0; idx < argc; ++idx)
            cout << argv[idx] << " ";
        cout << endl;

        return (0);
    }

The default constructor of the `class case_less` is used with the final argument of `sort()`. The only memberfunction that must be defined with the class `case_less` is the function object operator `operator()`. Since we know it's called with `string` arguments, we provide it with two `string` arguments, which are used in the `strcasecmp()` function. Furthermore, the `operator()` function is made inline, so that it does not produce overhead in the `sort()` function. The `sort()` function calls the function object with various combinations of `strings`, i.e., it thinks it does so. However, in fact it calls `strcasecmp()`, due to the inline-nature of `case_less::operator()`.

The comparison function object is often a predefined function object, since these are available for most of the common operations.

A function object may be defined inline. This is not possible for functions that are called indirectly (i.e., via pointers to functions). So, even if the function object needs to do very little work it has to be defined as an ordinary function if it is going to be called via pointers. The overhead of performing the indirect call may not outweight the advantage of the flexibility of calling functions indirectly. In these cases function objects that are defined as inline functions can result in an increase of efficiency of the program. Finally, function object may access the data of the objects for which they are called directly, as they have access to the private data of their object. In situations where a function must be able to serve many different datatypes (like the `qsort()` function) it is always somewhat cumbersome to reach the data of the involved objects via a pointer to a function of global scope.

In the following sections the available predefined function objects are presented, together with some examples showing their use. At the end of this section about function objects function adaptors are presented.

### 6.8.1: Categories of Function objects

Function objects may be defined when necessary. However, it is also (and often) possible to use predefined function objects. In order to use the predefined function objects the header file `functional` must be included:

            #include <functional>

The predefined function objects are used predominantly with the generic algorithms. Predefined function objects exists for arithmetic, relational, and logical functions. They are discussed in the coming sections.

6.8.1.1: Arithmetic Function Objects

The arithmetic function objects support the standard arithmetic operations: addition, subtraction, multiplication, division, modulus and negation. By using the predefined function objects, the corresponding operator of the associated data type is invoked. For example, for addition the function object `plus<Type>` is available. If we set `type` to `unsigned` then the `+` operator for unsigneds is used, if we set `type` to `string`, then the `+` operator for strings is used. For example:

    #include <iostream>
    #include <string>
    #include <functional>

    int main(int argc, char **argv)
    {
        plus<unsigned>
            uAdd;       // function object to add unsigneds

        cout << "3 + 5 = " << uAdd(3, 5) << endl;

        plus<string>
            sAdd;       // function object to add strings

        cout << "argv[0] + argv[1] = " << sAdd(argv[0], argv[1]) << endl;
    }

Why is this useful? Note that the function object can be used for all kinds of data types, not only on the predefined datatypes, but on any (class) type in which the particular operator has been overloaded. Assume that we want to perform an operation on a common variable on the one hand and on each element of an array in turn. E.g., we want to compute the sum of the elements of an array, or we want to concatenate all the strings in a text-array. In situations like these the function objects come in handy. As noted before, the function objects are most heavily used in the context of the generic algorithms, so let's take a quick look at one of them.

One of the generic algorithms is called `accumulate`. It visits all elements implied by an iterator-range, and performs a requested binary operation on a common element and each of the elements in the range, returning the accumulated result after visiting all elements. For example, the following program accumulates all its command line arguments, and prints the final string:

    #include <iostream>
    #include <string>
    #include <functional>
    #include <numeric>

    int main(int argc, char **argv)
    {
        string
            result =
                accumulate(argv, argv + argc, string(""), plus<string>());

        cout << "All concatenated arguments: " << result << endl;
    }

The first two arguments define the (iterator) range of elements to visit, the third argument is `string("")`. This anonymous string object provides an initial value. It could as well have been initialized to
`string("All concatenated elements: ")`
in which case the `cout` statement could have been a simple
`cout << result << endl`
Then, the operator to apply is `plus<string>()`. Here it is important to note the function call notation: it is not `plus<string>`, but rather `plus<string>()`. The final concatenated string is returned.

Now we define our own class data type `Time`, in which the `operator+()` has been overloaded. Again, we can apply the predefined function object `plus`, now tailored to our newly defined datatype, to add times:

    #include <iostream>
    #include <strstream>
    #include <string>
    #include <vector>
    #include <functional>
    #include <numeric>

    class Time
    {
        public:
            Time(unsigned hours, unsigned minutes, unsigned seconds)
            {
                days = 0;
                this->hours   = hours;
                this->minutes = minutes;
                this->seconds = seconds;
            }
            Time(Time const &other)
            {
                this->days    = other.days;
                this->hours   = other.hours;
                this->minutes = other.minutes;
                this->seconds = other.seconds;
            }
            Time const operator+(Time const &rValue) const
            {
                Time
                    added(*this);
                added.seconds   += rValue.seconds;
                added.minutes   += rValue.minutes   + added.seconds / 60;
                added.hours     += rValue.hours     + added.minutes / 60;
                added.days      += rValue.days      + added.hours   / 24;
                added.seconds   %= 60;
                added.minutes   %= 60;
                added.hours     %= 24;
                return (added);
            }
            operator char const *() const
            {
                static ostrstream
                    timeString;

                timeString.seekp(ios::beg);
                timeString << days << " days, " << hours << ":" <<
                            minutes << ":" << seconds << ends;
                return (timeString.str());
            }
        private:
            unsigned
                days,
                hours,
                minutes,
                seconds;
    };

    int main(int argc, char **argv)
    {
        vector<Time>
            tvector;

        tvector.push_back(Time( 1, 10, 20));
        tvector.push_back(Time(10, 30, 40));
        tvector.push_back(Time(20, 50,  0));
        tvector.push_back(Time(30, 20, 30));

        cout <<
            accumulate
            (
                tvector.begin(), tvector.end(),
                Time(0, 0, 0), plus<Time>()
            ) << endl;

    }

Note that all memberfunctions of `Time` in the above source are inline functions. This approach was followed in order to keep the example relatively small, and to show explicitly that the `operator+()` function may be an inline function. On the other hand, in real life the `operator+()` function of `Time` should probably not be made inline, due to its size. Considering the previous discussion of the `plus` function object, the example is pretty straightforward. The class `Time` defines two constructors, the second one being the copy-constructor, it defines a conversion operator (operator char const *()) to produce a textual representation of the stored time (deploying an `ostrstream` object, see chapter 11), and it defines its own `operator+()`, adding two time objects.

The organization of the `operator+()` deserves some attention. In expressions like `x + y` neither `x` nor `y` are modified. The result of the addition is returned as a temporary value, which is then used in the rest of the expression. Consequently, in the `operator+()` function the `this` object and the `rValue` object must not be modified. Hence the `const` modifier for the function, forcing `this` to be constant, and the `const` modifier for `rValue`, forcing `rValue` to be constant. The sum of both times is stored in a separate `Time` object, a copy of which is then returned by the function.

In the `main()` function four `Time` objects are stored in a `vector<Time>` object. Then, the `accumulate()` generic algorithm is called to compute the accumulated time. It returns a `Time` object, which cannot be inserted in the `cout ostream` object. Fortunately, the conversion operator is available, and this conversion operator is called implicitly to produce the required `char const *` string from the `Time` object returned by the `accumulate()` generic algorithm.

While the first example did show the use of a named function object, the last two examples showed unnamed or anonymous objects which were passed to the (`accumulate`) function.

The following arithmetic objects are available as predefined objects:

- `plus`, as shown this object calls the `operator+()`
- `minus`, calling `operator-()` as a binary operator,
- `multiplies`, calling `operator*()` as a binary operator,
- `divides`, calling `operator/()`,
- `modulus`, calling `operator%()`,
- `negate`, calling `operator-()` as a unary operator.

An example using the unary `operator-()` is the following, in which the `transform()` generic algorithm is used to toggle the signs of all elements in an array. The `transform()` generic algorithm expects two iterators, defining the range of objects to be transformed, an iterator defining the begin of the destination range (which may be the same iterator as the first argument) and a function object defining a unary operation for the indicated data type.

    #include <iostream>
    #include <string>
    #include <functional>
    #include <algorithm>

    int main(int argc, char **argv)
    {
        int
            iArr[] = { 1, -2, 3, -4, 5, -6 };

        transform(iArr, iArr + 6, iArr, negate<int>());

        for (int idx = 0; idx < 6; ++idx)
            cout << iArr[idx] << ", ";

        cout << endl;
    }

6.8.1.2: Relational Function Objects

The relational operators may be called from the relational function objects. All standard relational operators are supported: `==, !=, >, >=, <` and `<=`. The following objects are available:

- `equal_to<Type>`, calling `operator==()`,
- `not_equal_to<Type>`, calling `operator!=()`,
- `greater<Type>`, calling `operator>()`,
- `greater_equal<Type>`, calling `operator>=()`,
- `less<Type>`, calling `operator<()`,
- `less_equal<Type>`, calling `operator<=()`.

Like the arithmetic function objects, these function objects can be used as named and unnamed objects. An example using the relational function objects using the generic algorithm `sort()` is:

    #include <iostream>
    #include <string>
    #include <functional>
    #include <algorithm>

    int main(int argc, char **argv)
    {
        sort(argv, argv + argc, greater_equal<string>());
        for (int idx = 0; idx < argc; ++idx)
            cout << argv[idx] << " ";
        cout << endl;

        sort(argv, argv + argc, less<string>());
        for (int idx = 0; idx < argc; ++idx)
            cout << argv[idx] << " ";
        cout << endl;

        return (0);
    }

The `sort()` generic algorithm expects an iterator range and a comparator object for the underlying data type. The example shows the alphabetic sorting of strings and the reversed sorting of strings. By passing `greater_equal<string>()` the strings are sorted in decreasing order (the first word will be the 'greatest'), by passing `less<string>()` the strings are sorted in increasing order (the first word will be the 'smallest').

Note that the type of the elements of `argv` is `char *`, and that the relational function object expects a `string`. The relational object `greater_equal<string>()` will therefore use the `>=` operator of strings, but will be called with `char *` variables. The conversion from `char *` arguments to `string const &` parameters is done implicitly by the `string(char const *)` constructor.

6.8.1.3: Logical Function Objects

The logical operators are called by the logical function objects. The standard logical operators are supported: `&&, ||` and `!`. The following objects are available:

- `logical_and<Type>`, calling `operator&&()`,
- `logical_or<Type>`, calling `operator||()`,
- `logical_not<Type>`, calling `operator!()` (unary operator).

An example using the `operator!()` is the following trivial example, in which the `transform()` generic algorithm is used to transform the logical values stored in an array:

    #include <iostream>
    #include <string>
    #include <functional>
    #include <algorithm>

    int main(int argc, char **argv)
    {
        bool
            bArr[] = {true, true, true, false, false, false};
        unsigned const
            bArrSize = sizeof(bArr) / sizeof(bool);

        for (int idx = 0; idx < bArrSize; ++idx)
            cout << bArr[idx] << " ";
        cout << endl;

        transform(bArr, bArr + bArrSize, bArr, logical_not<bool>());

        for (int idx = 0; idx < bArrSize; ++idx)
            cout << bArr[idx] << " ";
        cout << endl;

        return (0);
    }

### 6.8.2: Function Adaptors

Function adaptors modify the working of existing function objects. There are two kinds of function adaptors:

- Binders are function adaptors converting binary function objects to unary function objects. They do so by binding one object to a fixed function object. For example, with the `minus<int>` function object, which is a binary function object, the first argument may be fixed to 100, meaning that the resulting value will always be `100` minus the value of the second argument. Either the first or the second argument may be bound to a specific value. To bind the first argument to a specific value, the function object `bind1st()` is used. To bind the second argument of a binary function to a specific value `bind2nd()` is used. As an example, assume we want to count all elements of a vector of `Person` objects that exceed (according to some criterion) some reference `Person` object. For this situation we pass the following binder and relational function object to the `count_if()` generic algorithm:

              bind2nd(greater<Person>(), referencePerson)

  The `count_if()` generic algorithm visits all the elements in an iterator-range, returning the number of times the predicate specified in its final argument returns `true`. Each of the elements of the iterator range is given to the predicate, which is therefore a unary function. By using the binder the binary function object `greater()` is adapted to a unary function object, comparing each of the elements in the range to the reference person. Here is, to be complete, the call of the `count_if()` function:

              count_if(pVector.begin(), pVector.end(),
                  bind2nd(greater<Person>(), referencePerson))

- The negators are function adaptors converting the truth value of a predicate function. Since there are unary and binary predicate functions, there are two negator function adaptors: `not1()` is the negator to be used with unary function adaptors, `not2()` is the negator to be used with binary function objects.

If we want to count the number of persons in a `vector<Person>` vector not exceeding a certain reference person, we may, among other approaches, use either of the following alternatives:

- Use a binary predicate that directly offers the required comparison:

              count_if(pVector.begin(), pVector.end(),
                  bind2nd(less_equal<Person>(), referencePerson))

- Use `not2` in combination with the `greater()` predicate:

              count_if(pVector.begin(), pVector.end(),
                  bind2nd(not2(greater<Person>()), referencePerson))

- Use `not1` in combination with the `bind2nd()` predicate:

              count_if(pVector.begin(), pVector.end(),
                  not1(bind2nd((greater<Person>()), referencePerson)))

  The following small example illustrates the use of the negator function adaptors, completing the section on function objects:

      #include <iostream>
      #include <functional>
      #include <algorithm>
      #include <vector>

      int main(int argc, char **argv)
      {
          int
             iArr[] = { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10};

          cout << count_if(iArr, iArr + 10, bind2nd(less_equal<int>(), 6)) <<
              endl;
          cout << count_if(iArr, iArr + 10, bind2nd(not2(greater<int>()), 6)) <<
              endl;
          cout << count_if(iArr, iArr + 10, not1(bind2nd(greater<int>(), 6))) <<
              endl;

          return (0);
      }

## 6.9: Overloadable Operators

The following operators can be overloaded:

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

However, some 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, as we have seen in section 6.5.

- Next chapter
- Previous chapter
- Table of contents