はい、できますが、配列メンバーとして宣言することはできません。参照を使用できます:
struct s {
int ( & extra_arr )[];
s() : extra_arr( reinterpret_cast< int (&)[] >( this[1] ) {}
};
実際には、これはポインターに相当するストレージを使用しますが、理論的にはその必要はありません。このクラスは POD ではありません。これは、理論と実践の違いによるものです。
reinterpret_cast
または、を非静的メンバー関数に入れることもできます。
struct s {
int ( & get_extra() )[]
{ return reinterpret_cast< int (&)[] >( this[1] ); }
int const ( & get_extra() const )[]
{ return reinterpret_cast< int const (&)[] >( this[1] ); }
};
現在、アクセスには関数呼び出し構文が必要です (インライン化により、デバッグ ビルド以外のマシン コードの区別がなくなります) が、無駄なストレージはなく、オブジェクトは POD ルールの他の例外を除いて POD になります。
このように ABI を少し調整するだけで、#pragma pack
完全な C バイナリ互換性を得ることができます。いずれにしても、シリアライゼーション アプリケーションでは、このような調整が必要になることがよくあります。
また、これは const-correctness をサポートしていますが、前のソリューションでは const オブジェクトの変更が許可されていました (配列が同じオブジェクトの一部であることを認識していないため)。
ボイラープレートは、CRTP 基本クラス (C++11 では派生クラスを POD にすることもできます)、または C++ アクセサーまたは C フレキシブル メンバーのいずれかを定義するために展開されるプリプロセッサ マクロに一般化できます。
これらの解決策はどちらも元の C 以外のことをしないことに注意してください。特別なメンバー関数は柔軟な配列をコピーせず、クラスは関数パラメーターまたはサブオブジェクトをサポートできません。