4

在为这个问题编写测试代码时,我发现下面的注释行不能在 GCC 4.7.2 上编译:

#include <thread>
#include <iostream>

struct S {
    void f() {
        std::cout << "Calling f()" << std::endl;
    }
};

int main()
{
    S s;
    // std::thread t(&S::f, s); // does not compile?
    std::thread t(&S::f, &s);
    t.join();
}

但是 cppreference 似乎声称“this”参数可以等效地作为对象、对对象的引用或指向对象的指针传递:

如果 f 是指向类 T 的成员函数的指针,则调用它。返回值被忽略。实际上,执行以下代码: (t1.*f)(t2, ..., tN) 如果 t1 的类型是 T,则引用 T 或引用派生自 T 的类型。 ((*t1).* f)(t2, ..., tN) 否则。

我实际上认为这听起来很糟糕,并且宁愿std::thread只允许指针或引用语义而不是互换地接受它们,但鉴于它似乎应该这样做,以上是 GCC/libstdc++ 错误(还是我误解了 cppreference)?

4

1 回答 1

4

好像今晚是GCC 错误派对:-)

除了笑话,这肯定是一个错误我对链接问题的回答实际上包含了证明,但由于没有强调,我将在此重复。

这就是C++11 标准中定义的构造函数INVOKE的行为(参见链接的答案)的设施的方式std::thread

定义INVOKE (f, t1, t2, ..., tN)如下:

(t1.*f)(t2, ..., tN) 当 f 是指向类 T 的成员函数的指针并且 t1 是类型 T 的对象或对类型 T 的对象的引用或对从 T 派生的类型的对象;

— ((*t1).*f)(t2, ..., tN) 当 f 是指向类 T 的成员函数的指针且 t1 不是上一项中描述的类型之一时;

— t1.*f 当 N == 1 且 f 是指向类 T 的成员数据的指针且 t1 是类型 T 的对象或对类型 T 的对象的引用或对派生于的类型的对象的引用T;

— (*t1).*f 当 N == 1 且 f 是指向类 T 的成员数据且 t1 不是上一项中描述的类型之一时;

— f(t1, t2, ..., tN) 在所有其他情况下。

粗体的句子有效地指定了以下行:

std::thread t(&S::f, s);

应该编译。因此,这被称为错误

此外,这确实在 GCC 4.8.0 (beta) 和 Clang 3.2 上编译。

于 2013-02-26T02:53:59.580 回答