2017-11-01 7 views
7
struct root 
{ 
    int i = 0; 
}; 

struct base: root{}; 
struct derive: base{}; 

constexpr derive d0; 

int main() 
{ 
    constexpr auto& r = static_cast<root const&>(d0); 
    constexpr auto& b = static_cast<base const&>(r); 
    constexpr auto& d = static_cast<derive const&>(r); 

    static_assert(d0.i == 0, ""); // ok 
    static_assert(r.i == 0, ""); // ok 
    static_assert(b.i == 0, ""); // error in gcc 
    static_assert(d.i == 0, ""); // ok 
} 

クラン下にエラーでコンパイル上記のコードが、GCC 7.2.0を受け入れる:値にアクセスする場合にのみ、「i」は、中間ベースを介しconstexprのされていない中間抽象クラス参照から基本クラスメンバにアクセスするconstexprですか?

prog.cc:17:5: error: non-constant condition for static assertion 
    static_assert(b.i == 0, ""); 
    ^~~~~~~~~~~~~ 
prog.cc:17:5: error: accessing value of 'd.derive::<anonymous>.base::<anonymous>' through a 'const base' 
glvalue in a constant 

。 どのコンパイラが正しいですか?

+0

コンパイルするC++の仕様は何ですか? C++ 17? – dlasalle

+0

は、C++ 14とC++ 17の両方でコンパイルされても同じ結果を示します。 – kwanti

+0

興味深い使用例です。私はそれがおそらくgccによって許可されるべきだと思うという点でチャイムしたいと思いますが、おそらく彼らはそれが安全でないと保証しなかったかもしれません。 (ダウンキャストのための 'dynamic_cast'のみ) – AndyG

答えて

-2

ベースクラスから派生クラスへは、非標準レイアウトクラス(仮想メンバまたは非公開メンバまたはベースまたは複数継承を持つクラス)間のstatic_castのようにUBです。だから、あなたが公共の継承を必要とする明確に定義された

struct base : public root{}; 
struct derive : public base{}; 

を上記のコードを作るために、あなたが唯一のstatic_castderiveからできbaseまたはrootに、そしてbaseからrootのではなく、他の方向に移動します。

GCCの通常のセマンティクスでは、あなたのコードを受け入れる必要がありますが、非標準的な振る舞いに依存しているため、コードは受け入れられません。

+0

構造体はデフォルトでパブリックに継承されるため、問題はありません。 – bstamour

+0

ベースから派生クラスへの 'static_cast'は、非標準レイアウトクラス間の' static_cast'と同様に、よく定義されています。 – Oktalist

関連する問題