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ポインターまたは参照セマンティクスを交換可能に受け入れるのではなく、どちらか一方のみを許可することを好みます.

4

1 に答える 1

4

今夜はGCC Bug Partyのようです:-)

冗談はさておき、これは間違いなくバグです。リンクされた質問に対する私の回答には実際に証明が含まれていますが、強調されていないため、ここで繰り返します。

これは、のコンストラクターの動作(リンクされた回答を参照)が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 (ベータ) および Clang 3.2 での行コンパイルも行います。

于 2013-02-26T02:53:59.580 に答える