11.4.  Function Pointers and Functors

[ fromfile: functors.xml id: functors ]

Functors are generalized callable structures that can be invoked. Regular C and C++ functions, which readily convert to function pointers, fall into this category. Generic algorithms are typically overloaded to accept various categories of callables as parameters. Example 11.12 demonstrates how to invoke functions indirectly via function pointers.

Example 11.12. src/functors/pointers/main.cpp

#include <QtGui>

QString name() {
    return QString("Alan");
}

typedef QString (*funcPtr)();               1
Q_DECLARE_METATYPE(funcPtr);                2

int main() {
    qRegisterMetaType<funcPtr>("funcPtr");  3
    funcPtr ptr = name;                     4

    QString v = (*ptr)();                   5
    qDebug() << v << endl;                  6
}

1

A function that returns QString and takes no args.

2

Declare, so we can use in QVariant.

3

Register, so we can use in queued signal parameters.

4

Function names evaluate to pointers to functions.

5

Invoke a method by dereferencing function ptr.

6

Prints "Alan"


Pointers to functions are frequently used in C for callbacks, or functions that need to be called in response to certain events. In C++, it is possible to use object-oriented, template-based mechanisms as well. This way, you can specify the types of the arguments and return type at compile-time, making their use type-safe.

A functor in C++ is a callable object that behaves like a function pointer, in the sense that it can be dereferenced and called like a function. The C++ standard libs that comply with TR1[83] or later provide base class types for these in the <functional> header file. The C++ function call operator provides part of the syntactic sugar that makes objects act like functions. The types std::unary_function and std::binary_function provide additional type information on C++ functors. They are parameterized base class types you can extend, for use in QtAlgorithms, C++ STL and the Qt Concurrent library. Example 11.13, shows how to define functors that can be used in places where function pointers are found.

Example 11.13. src/functors/operators/functors.h

[ . . . . ]
class Load : public std::unary_function<QString, QImage> {         1
public:
    QImage operator() (const QString& imageFileName) const {
        return QImage(imageFileName);
    }
};
class Scale {
    public:
    typedef QImage result_type;                                    2
    QImage operator() (QImage image) const {
        for (int i=0; i<10; ++i) {
            QImage copy = image.copy();
            copy.scaled(100, 100, Qt::KeepAspectRatio);
        }
        if (image.width() < image.height()) {
            return image.scaledToHeight(imageSize,
                                        Qt::SmoothTransformation);
        }
        else {
            return image.scaledToWidth(imageSize, 
                                       Qt::SmoothTransformation);
        }
    }
};
class LoadAndScale : public std::unary_function<QString, QImage> { 3
public:
    Scale scale;
    QImage operator() (const QString& imageFileName) const {
        QImage image(imageFileName);
        return scale(image);
    }
};
[ . . . . ]

1

Defines result_type.

2

A trait required for functor objects.

3

Also defines result_type.


In Example 11.14 a temporary instance of LoadAndScale is created and passed to a QtConcurrent algorithm, which is overloaded to accept function pointers and std::unary_function objects for its mapping function. QtConcurrent is discussed in more detail in Section 17.2.

Example 11.14. src/functors/operators/imagefunctor.cpp

[ . . . . ]

        connect(m_futureWatcher, SIGNAL(progressValueChanged(int)),
                this, SIGNAL(progressCurrent(int)));
        emit statusMessage("Loading and Transforming in parallel");
        m_futureWatcher->setFuture(QtConcurrent::mapped(files,
                                                  LoadAndScale()));



[83] C++ Technical Report 1 (TR1) is a draft document containing proposed additions to the C++ Standard Library that are likely to be included in the next official standard. See this Wikipedia article for more information.