2016-06-23 14 views
7

次のコードはC++で明確に定義されていますか? (*)不完全な型のデータメンバへのポインタ

標準で見る場所を見つけても苦労していて、ウェブを検索しても何も具体的なものが見つかっていません。それが動作する(またはに思える)GCCとクラン(のx86/x86_64版)の新しいバージョンではなく、Visual Studioの2015で失敗する(**)ので

struct S; 
struct T { 
    constexpr T() = default; 
    bool S::* a = nullptr; 
    int b  = 42; 
}; 
const T t{}; 
// Test. Compiled using: cl /W4 /WX /FAs filename.cpp 
#include <stdlib.h> 
int main() { 
    if (t.b != 42) abort(); 
} 

私が求めている理由は、アップデート2と3を更新していますRC。

バグを報告する前に、私が未定義の動作に頼っているのではなく、適切な用語を検索していないことを確認したいと思います。

this postで述べたように/vmg/vmbを試してみました。

(*):私は主にC++ 14以降を気にしていますが、答えがC++ 11には適用されない理由はありません。
(**):コードが明確に定義されている場合は、コードジェネレータバグのように見えますが、ポインタの割り当て場所ではありません。 struct Sからstruct S{}に変更すると、コードが「仕事」になるようです。

+1

コードでは、正確に何を期待していますか? 'T'は' S'へのポインタを含むはずです、もしそうなら 'S * a = nullptr;'と書かれているのはなぜですか? – Xirema

+0

コンパイル[ここ](http://rextester.com/NFYP31324)と私自身のMSVS 2015です。バージョン14.0.23107.0を持っています。D14REL – NathanOliver

+1

@ Xirema: 'T :: a'は[bool]データへのポインタですメンバ](http://en.cppreference.com/w/cpp/language/pointer#Pointers_to_data_members)を不完全な型 'S'で返します。 @ NathanOliver:それは私のためにコンパイルされますが、実行されると '中止されます。 – user786653

答えて

5

コードが明確に定義されている:場合

N4594 3.2/5

[...] クラス型Tは、完全でなければならない:

  • (5.1) タイプTのオブジェクトが定義されている(3.1)、または
  • (5.2) タイプTの非静的クラスのデータメンバーが宣言されているED(9.2)、又は
  • (5.3) Tは、オブジェクト・タイプまたは配列要素タイプ新しい式(5.3.4)で、又は
  • (5.4) 左辺ツー右辺値変換として使用されます式がタイプT(4.1)、または
  • (5.5) の式を暗黙的または明示的にT型に変換する場合に適用されます(第4,5,2.3,5.2.7,5.2項(5.6) ヌルポインタ定数ではなく、cv void *以外の型を持つ式は、標準変換を使用してTへのポインタまたはTへのポインタへ変換されます( )。 (Clau (5.2.5)、
  • (5.7) クラスメンバーアクセス演算子は、T(5.2.5)型の式に適用されます。
  • (5.8) 型ID演算子(5.2.8)またはsizeof演算子(5.3.3)
  • (5.9) の戻り型や引数型を持つ関数をT型のオペランドに適用されるか、またはタイプTの基底クラスが定義されているクラス(第10項)、または
  • (012)、 (タイプ10)、または
  • (5.11) T型の左辺値が(5.18)に、または
  • (5。タイプTが式のアラインメントの対象(5.3.6)、または
  • (5.13) 例外の宣言にはT型、Tへの参照、Tへのポインタ(15.3)があります。それらの

なしTへのポインタメンバーTを宣言するために完了する必要があると述べていません。

+0

ありがとう!誰かが標準のどこかで反対の声明を見つけることができない限り、私はこの回答を1日かそこらで受け入れます。 – user786653

+0

@ user786653 – PcAF

関連する問題