1

If you write something like this: QFuture<bool> thread_res = QtConcurrent::run([]() {}); under the hood there is template magic, and question is it valid c++ code.

1)template <typename T> class QFutureInterface has method

QtPrivate::ResultStore<T> &resultStore()
{ return static_cast<QtPrivate::ResultStore<T> &>(resultStoreBase()); }

(Here's link to Qt sources to above method. )

2)resultStoreBase return ResultStoreBase& with such hieracity template <typename T> class ResultStore : public ResultStoreBase, and ResultStoreBase& really reference to ResultStoreBase object, NOT QtPrivate::ResultStore<T>

In other words we have something like this:

#include <map>

class Base {
public:
    virtual ~Base() {}
protected:
    std::map<int, std::string> results_;
};

template <typename T>
class Derived : public Base {
public:
    void clear() {
        results_.clear();
    }
};

struct Foo {
    Base base;
    template <typename T>
    Derived<T> &f() {
        return static_cast<Derived<T> &>(base);
    }
};

int main()
{
    Foo foo;
    foo.f<bool>().clear();
}

template<class T> class Derived have no data, and foo.f<bool>() used only to call methods, not to copy object or destroy object, so the only one method which can be called via vptr - destructor never called via such interface.

So question is this code have undefined behavior?

According to this c++ design: cast from base to derived class with no extra data members such code have undefined behavior any way, but then why Qt guys wrote it in such way?

Community
  • 1
  • 1
fghj
  • 8,898
  • 4
  • 28
  • 56
  • The reason is pragmatic: not all behavior is undefined in *practice*. It can be implementation defined, and in this case, is. So yes, the code has undefined behavior according to the standard, but you're not running an abstract idea of a compiler, but real software whose developers have decided to make the behavior defined. Remember that undefined behavior is a minimal guarantee, any implementation can be standards compliant and replace undefined behavior with implementation-defined one! – Kuba hasn't forgotten Monica Mar 29 '16 at 18:22
  • But any code that use QtConcurent crash if compiled with `-fsanitize=address,undefined` – fghj Mar 29 '16 at 18:24
  • 1
    You can't just casually drop that without saying exactly what compiler, what platform, what binary package the compiler came in, and once you do, it doesn't belong here, but in a bug tracker - most likely Qt's. – Kuba hasn't forgotten Monica Mar 29 '16 at 18:26
  • I think this question is asking for help understanding the code, and as such I think it is a valid question, even if answer turns out to be "it's a bug, don't do it yourself". Still, links to full original source code, as well as compiler used for the crash, would be great... – hyde Mar 29 '16 at 18:32
  • 1
    @KubaOber `You can't just casually drop` you mean crash with `-fsanitize=address,undefined`? This happens on every platform that support clang/gcc/sanitalizer (linux+amd64,x86,arm,arm64 and so on), because of it sanitzier think that static cast from base to derived undefined behavior. So before go to bugzilla I need decide who's bugzilla in charge Qt, or may be clang/gcc/sanitizer – fghj Mar 29 '16 at 18:35
  • "This happens on every platform that support clang/gcc/sanitalizer" Wonderful, but I can't divine that. This is a Qt "bug", but I doubt that it'll get fixed anytime soon other than by adding a pragma to disable the sanitizer for the offending code. In practice, without sanitization, this results in safe platform-defined behavior. You're welcome, of course, to submit a fix with your bug report :) – Kuba hasn't forgotten Monica Mar 29 '16 at 18:37

0 Answers0