Today, I did the most evil hack I’ve done so far in a real project. It is not something I plan to keep in the code, but it is cool enough to be shared.

Do not use something like this. Ever.

I’ve found out that QFuture can contain an exception in the case something in the asynchronous process failed. This is nice, because it (even if Qt generally does not like exceptions) provides a nice error reporting mechanism for asynchronous tasks

The problem is that in order to access the exception, you need to invoke some of the blocking methods like result() or waitForFinished(). And I hate methods that block.

Before I propose a patch for QFuture to allow testing for an exception, I had to find a way to access this data without it really being supported. The exception store is located in a private (pimpled) class in the QFuture.

So, how to access something that is private from the outside?

One possibility is #define private public but that is just overly crude for my taste.

The second, and much more interesting one comes after realizing that QFuture is a templated class, and a templated class is not really closed. The access restrictions do not apply to different instantiations of a templated class, so if we can create an instantiation of a method in QFuture for some class that does not really exist, and is not used anywhere else in the world, and we will be able to access its privates.

class QFutureAccessHack_hasException;
template <>
inline bool QFuture<QFutureAccessHack_hasException>
    ::isCanceled() const
{
    return d.exceptionStore().hasException();
}

And, from now on, this instantiation of the method can be used to check whether a specific future contains an exception.

template <typename T>
bool hasException(const QFuture<T> &future)
{
    return
        // As soon as you see a reinterpret_cast somewhere,
        // you just know it is used to commit an atrocity
        reinterpret_cast<
            const QFuture<QFutureAccessHack_hasException>*>(
            &future)
        ->isCanceled();
}

Everyone talks about the power of templates, and the possibility to calculate stuff at compile-time. But they are much more powerful than that. :)

p.s. Yes, it would have been much easier to just roll my own qfuture.h