web-dev-qa-db-ja.com

C ++ 11-非静的データメンバーを 'auto'として宣言する

C++ 11では、宣言で初期化されている場合、非静的データメンバーを 'auto'として宣言できますか?例えば:

struct S
{
    auto x = 5;  // in place of 'int x = 5;', which is definitely allowed
};

GCC 4.7は上記のコードを拒否しますが、int x = 5;を受け入れます。

これがコンパイラのバグではなく、標準で実際に許可されていないと仮定すると、なぜですか?ローカル変数autoを宣言するのと同じくらい便利です。

48
HighCommander4

非静的メンバーを禁止するルールは、7.1.6.4の第4項にあります。

Auto type-specifierは、選択ステートメント(6.4)または反復ステートメント(6.5)の条件で変数を宣言する場合にも、new-type-idまたはtype-idのtype-specifier-seqで使用できます。新しい式(5.3.4)、for-range-declaration、およびstaticデータメンバーを中括弧または等しいで宣言する-クラス定義のメンバー指定(9.4.2)内に現れる初期化子。

私はそれの根拠が静的であることを発見しました here James McNellisがコメントでそれを説明する方法を反映しています。

ある国の組織は、静的でないものに対して自動型指定子を許可することを嫌っています。電子メールから著者へ:

    template< class T >
    struct MyType : T {
      auto data = func();
      static const size_t erm = sizeof(data);
    };

Xのレイアウトを決定するために、2フェーズの名前ルックアップとADLがあります。 funcはタイプまたは関数のいずれかであることに注意してください。これは、T、MyTypeの名前空間、インスタンス化されたときのTの関連する名前空間、グローバル名前空間、匿名名前空間、またはusingディレクティブの対象となる名前空間にあります。運がよければ、おそらくいくつかのconcept_mapルックアップをスローすることができます。ヘッダーインクルードの順序によっては、ADLの結果が異なる場合があり、1つの定義ルールに違反する可能性があります。これは、診断する必要はありません。

この論争のため、著者はもはや非静的データメンバーに対してautoを許可することを提案しません。

したがって、基本的にヘッダーのインクルードの順序によっては、dataのタイプが大きく異なる可能性があります。もちろん、 auto x = 5;は、2フェーズの名前検索またはADLに依存する必要はありませんが、それ以外の場合は、すべてのユースケースに個別のルールを作成する必要があるため、それらを「ブランケット」ルールにしたと想定しています。とても難しい。

同じ論文で、著者はこの制限を排除することを提案していますが、この提案はおそらく上記の理論的根拠のために拒否されたようであり、そのため、初期化子が何であっても期待される動作は同じになる可能性があります。

63
Jesse Good

その他の場合:

C++ 17を使用すると、これは間接的に(非静的メンバー型の自動推定)可能です。それを実現するには、テンプレートと控除ガイドを使用する必要があります。

template< class data_t>
struct MyType 
{
    data_t data;
    static constexpr auto data_size = sizeof(data_t);

    MyType( data_t && p_data ) : data(p_data) {}
};

template< class data_t>
MyType(data_t &&) -> MyType<std::remove_reference_t<data_t>>;

方法はわかりませんが、この自動メンバーは実際には、特定のパターンが不可能に近い言語なしで言語にする必要があります。

上記のシナリオは、ラムダが参照によってクラスのメンバーをキャプチャする場合に機能します機能しません。これは、型消去関数の使用を回避する高度に補正可能なクラスに役立つパターンです。組み込みシステムで定期的に行うこと。

https://godbolt.org/z/W-K9Uk

言語を変形して提出に移すと、lambdaは、placement-newとoffset_ofを使用して、存在しないクラスのメンバーを参照できますが、これは馬鹿げているため、必須ではありません。

0
David Ledger