【问题标题】:How does Qt bind pointers-to-non-static-member-functions in QtConcurrent?Qt 如何在 QtConcurrent 中将指针绑定到非静态成员函数?
【发布时间】:2011-11-16 17:25:32
【问题描述】:

来自QtConcurrent documentation

QByteArray bytearray = "hello world";
QFuture<QList<QByteArray> > future = QtConcurrent::run(bytearray, &QByteArray::split), ',');
...
QList<QByteArray> result = future.result();

上面的代码 sn-p 似乎以类似于std::tr1::bind 的方式绑定一个函数(std::bind for > C++11)。也就是说,它采用非静态成员函数 (QByteArray::split()) 并(稍后)在它所属的对象的特定实例上调用它(我们提供为 bytearray)。

Qt 是如何做到这一点的?是在幕后使用std::tr1::bind 还是boost::bind

The documentation 也指代您使用 std::tr1boost 的情况,但我不完全理解 绑定函数 在这种情况下的含义。上述情况实际上是否与您可能使用tr1boost 的其他情况不同/更专业/更简单?

我试图通过源头找到自己的方式,但很快就迷路了!

【问题讨论】:

    标签: c++ qt c++11 qt4 qtconcurrent


    【解决方案1】:

    我将尝试一个自我回答,因为现有的答案(非常感谢@Mike Brown 和@skyhisi)奠定了基础,但不解决这个具体案例......

    来源:

    QtConcurrent::run(...) :

    template <typename T, typename Class>
    QFuture<T> run(const Class &object, T (Class::*fn)())
    {
      return (new QT_TYPENAME SelectStoredMemberFunctionCall0<T, Class>::type(fn, object))->start();
    }
    

    SelectStoredMemberFunctionCall0

    template <typename T, typename Class>
    struct SelectStoredMemberFunctionCall0
    {
      typedef typename SelectSpecialization<T>::template
        Type<StoredMemberFunctionCall0    <T, Class>,
          VoidStoredMemberFunctionCall0<T, Class> >::type type;
    };
    

    VoidStoredMemberFunctionCall0

    template <typename T, typename Class>
    class VoidStoredMemberFunctionCall0 : public RunFunctionTask<T>
    {
    public:
      VoidStoredMemberFunctionCall0(T (Class::*_fn)() , const Class &_object)
      : fn(_fn), object(_object){ }
    
      void runFunctor()
      {
        (object.*fn)();
      }
    private:
      T (Class::*fn)();
      Class object;
    };
    

    鉴于上述情况,我可以看到 Qt 在 normal way 中存储了一个指向成员函数的指针,但是通过将其装饰在模板中,否则会被忽视,从而产生了泛型的错觉。

    VoidStoredMemberFunctionCall0::object 的类型以及VoidStoredMemberFunctionCall0::fn 的签名都在上面传递给QtConcurrent::run 的参数中指定。

    说实话,我什至不知道这种“隐式”模板化是可能的。有人可以推荐进一步阅读吗?

    【讨论】:

    【解决方案2】:

    C++ FAQ 很好地解释了Pointers to member functions 并解释了陷阱。

    在某些时候会有类似的一行:

    ret_val = obj_ptr->*func_ptr(param);
    

    但它会被封装在模板中以允许传递任何对象类型和参数类型,并且其中也会混杂线程调度。

    【讨论】:

      【解决方案3】:

      您正在传递函数指针和声明函数的类的实例。调用它就像从对象中取消引用函数指针一样简单。 This StackOverflow Question 给出答案

      【讨论】:

      • 我知道QtConcurrent::run 必须使用指向成员函数的指针,我只是不明白它如何在函数返回类型、参数和对象时存储指针/调用函数其中它的成员不是在QtConcurrent 中硬编码,而是从提供给run(...) 的参数中提取。
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2010-11-02
      • 2018-01-02
      • 2014-03-06
      • 2012-12-28
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多