12

次のサンプルをコンパイルする必要がありますか?

struct B;
struct A
{
  A(B*&&){}
};

struct B : A
{
  B() : A(this){}
};

int main(){}

clangを使用したLWSではコンパイルされますが、gccを使用すると次のようになります。

'B*const'から'B*&&'への引数1の既知の変換はありません

追加するconstとコンパイルされます。

また、MSVCも間違っていることを指摘したいと思います。

パラメータ2を「B*const」から「B*&&」に変換できません

したがって、2つのコンパイラにバグがあるようです。

バグが提出されました

MSVCバグリンク

GCCバグリンク

4

2 に答える 2

8

はい、コンパイルする必要があります。

thisasを実装するのは正しくありませんcv T* const(ここで、cvは関数のcv修飾子でありT、クラスタイプです)。thisではなくconst、組み込み型の単なるprvalue式です(変更できません)。

多くの人は、変更できないので変更thisする必要があると考えていますconstが、Johannes Schaub --litbがかつてコメントしたように、はるかに優れた説明は次のようなものです。

// by the compiler
#define this (__this + 0)

// where __this is the "real" value of this

ここでは、変更できないことは明らかですがthis(たとえば、this = nullptr)、そのconstような説明には必要ないことも明らかです。(そして、コンストラクターにある値は、一時的な値にすぎません。)

于 2013-03-21T21:50:38.600 に答える
6

私はclangが正しいと言います-コードはコンパイルする必要があります。何らかの理由で、GCCは、次のことにもかかわらず、thisポインターが存在すると見なします。const

thisクラスのメンバー関数のタイプXはですX*。メンバー関数が宣言されている場合、constこれのタイプはです。メンバー関数が宣言されている場合、これのタイプはです。メンバー関数が宣言されている場合、これのタイプはです。const X*volatilevolatile X*const volatileconst volatile X*

したがって、この場合はthis、prvalueB*であり、に完全にバインド可能である必要がありB*&&ます。ただし、this右辺値参照にバインドする場合、の値はthis一時オブジェクトにコピーされ、代わりに参照がそれにバインドされることに注意してください。thisこれにより、元の値を実際に変更することはありません。

タイプ「cv1」への参照は、タイプ「cv2 T1」の式によって次のように初期化さT2れます。

  • [...]

  • [...]または参照は右辺値参照でなければなりません

    • 初期化式の場合

      • xvalue、class prvalue、array prvalue、またはfunction lvalueと[...]、または

      • クラスタイプがあります(つまり、T2はクラスタイプです)、[...]

      それから [...]

    • それ以外の場合は、タイプ「cv1 T1」の一時オブジェクトが作成され、非参照コピー初期化(8.5)のルールを使用して初期化式から初期化されます。次に、参照は一時的なものにバインドされます。[...]

于 2013-03-21T21:43:42.747 に答える