2 に答える
あなたは2つのバグに遭遇しました。
GCCの最初のバグは、「完全転送」値カテゴリの控除中に、それがgoo<int>
右辺値であると見なすことです。しかしgoo<int>
、実際には左辺値です。したがって、に推論するのではなく、に推論_Callable
するvoid(void (*)(int), int)
必要がありvoid(&)(void (*)(int), int)
ます。次に、参照を折りたたむvoid(&&)(void (*)(int), int)
と、GCCバージョンで誤って行われるようにではなく、その左辺値参照がパラメーター型として生成されます。
パラメータの実際の初期化中に、関数左辺値による右辺値参照パラメータの初期化も誤って拒否します(GCC4.5がリリースされたときの作業ドラフトの状態は覚えていませんが、ドラフトに問題があった可能性があります-当時形成された)。関数型式の場合、標準では、関数型の左辺値を使用して関数型への右辺値参照を初期化できます。
テンプレートIDを関数の左辺値に解決するのは非常に複雑なので、GCCがそれを間違えたのは驚きではありません(http://llvm.org/bugs/show_bug.cgi?id=7505およびhttp://llvm.orgを参照)。 /bugs/show_bug.cgi?id=7505は、一見単純なものに対して相互作用するルールの数の2つの例です)。
左辺値は、アドレスを取得できるオブジェクトを表す式です。たとえば、プリミティブ型への代入式の左側は左辺値でなければなりません:int i; i = 3;
は OK ですが、5 = 3
そうではありません。違いは、それ&i
は OK ですが、&5
そうではないということです。
goo<int>
は関数型の左辺値ですが、関数型の式は C および C++ では本質的に役に立ちません。これらは、アドレスを取得することにより、常に関数ポインターに変換されます。結果のポインターは、アドレスのアドレスを取得するため、左辺値ではありません。
G++ のバグは、アドレスが暗黙的に取得される場合に発生します。どうやら、非テンプレートを渡すとテンプレート推定の前に変換が行われますが、渡すと変換が行わgoo
れますgoo<int>
。コンストラクターが参照を受信しようとしないように、それを早期に行う必要があります。
&
変換を強制するには、単項演算子で十分です。
TH= std::thread(&goo<int>,ptr,1);