5

次のコードを検討してください。

class Foo;

Foo& CreateFoo();


void Bar()
{
   CreateFoo();
}

Visual Studioでは、これにより、Fooが未定義の型であるというエラーC2027が発生します。他のほとんどのコンパイラでは、正常にコンパイルされます。CreateFooの戻り値が割り当てられていない場合にのみ問題になります。行を次のように変更した場合:

Foo& foo = CreateFoo();

VisualStudioで正常にコンパイルされます。また、Fooが前方宣言されただけでなく定義されている場合は、割り当てなしで正常にコンパイルされます。

どちらが正しい動作である必要がありますか?これに対処するC++標準には何かありますか、それとも実装に任されているものですか?私はこれについて話しているものを見ましたが、何も見ませんでした。

更新: バグレポートが提出されました。

4

2 に答える 2

6

これは、標準の関連部分のように見えます (セクション 5.2.2):

関数呼び出しは、結果の型が左辺値参照型または関数型への右辺値参照である場合は左辺値、結果の型がオブジェクト型への右辺値参照である場合は xvalue、それ以外の場合は prvalue です。

関数呼び出しがオブジェクト型の prvalue の場合:

  • 関数呼び出しが次のいずれかの場合

    • decltype-specifierのオペランドまたは

    • decltype-specifierのオペランドであるコンマ演算子の右側のオペランド、

    prvalue の一時オブジェクトは導入されません。prvalue の型が不完全である可能性があります。[注: その結果、ストレージは prvalue に割り当てられず、破棄されません。したがって、このコンテキストでは関数呼び出しの型であるため、クラス型はインスタンス化されません。これは、式が関数呼び出し表記または演算子表記 (13.3.1.2) を使用するかどうかに関係なく当てはまります。— 終了注 ] [注: id-expression が括弧で囲まれているかどうかを考慮する decltype-specifier の規則 (7.1.6.2) とは異なり、このコンテキストでは括弧に特別な意味はありません。— 終了注記]

  • それ以外の場合、prvalue の型は完全でなければなりません。

この関数の結果の型は左辺値参照型であるため、関数呼び出しは左辺値に評価され、完全性の要件は適用されません。

このコードは、少なくともリリースされた Visual C++ のバージョンが完全に実装されていない C++11 では合法です。

于 2012-08-11T01:23:46.667 に答える
1

関数宣言では常に不完全な型を使用できますが(実際のコードではなく、関数のシグネチャのみを宣言するため)、使用する場合は使用できません。

呼び出しCreateFoo();はに等しく(void) CreateFoo();、変換には完全な型が必要なため、Visual Studioは変換を行うためにFooのコードを検査する必要があると思います(実際にvoid変換を記述できるかどうかはわかりません)。

についてはFoo & foo = CreateFoo();、これは変換を行わないので、不完全なタイプを持つことを回避できます。

于 2012-08-11T01:44:50.337 に答える