私は最近 Scott Meyers から新しいEffective modern C++ を購入し、今それを読んでいます。しかし、私は完全に私を悩ませている 1 つのことに遭遇しました。
項目 5 で、Scott は使用することautoは素晴らしいことだと述べています。入力を節約し、ほとんどの場合に正しい型を提供し、型の不一致の影響を受けない可能性があります。私はこれを完全に理解してautoおり、良いことだとも考えています。
しかし、項目 6 で、スコットは、すべてのコインには 2 つの面があると述べています。auto同様に、たとえばプロキシ オブジェクトの場合など、 が完全に間違った型を推測する場合もあります。
次の例はすでにご存知かもしれません。
class Widget;
std::vector<bool> features(Widget w);
Widget w;
bool priority = features(w)[5]; // this is fine
auto priority = features(w)[5]; // this result in priority being a proxy
// to a temporary object, which will result
// in undefined behavior on usage after that
// line
ここまでは順調ですね。
しかし、これに対するスコットの解決策は、いわゆる「明示的に型付けされた初期化子イディオム」です。アイデアは、次のように初期化子で static_cast を使用することです。
auto priority = static_cast<bool>(features(w)[5]);
しかし、これはより多くの型付けにつながるだけでなく、推論されるべき型を明示的に述べることも意味します。基本的にauto、明示的な特定の型に対する両方の利点を失います。
なぜこのイディオムを使用するのが有利なのか、誰か教えてもらえますか?
最初に物事を明確にするために、私の質問は、なぜ私が書くべきかを目的としています:
auto priority = static_cast<bool>(features(w)[5]);
それ以外の:
bool priority = features(w)[5];
@Sergey は、このトピックに関するGotWの素敵な記事へのリンクを提供してくれました。これは、私の質問に部分的に答えています。
ガイドライン: ローカル変数 auto x = type{ expr }; の宣言を検討してください。タイプに明示的にコミットしたい場合。コードが明示的に変換を要求していること、変数が初期化されることが保証されていること、および偶発的な暗黙的な縮小変換が許可されていないことを示すことは自己文書化されています。明示的な絞り込みが必要な場合にのみ、{ } の代わりに ( ) を使用してください。
これは基本的に関連する質問につながります。これらの4 つの選択肢のうち、どれを選択する必要がありますか?
bool priority = features(w)[5];
auto priority = static_cast<bool>(features(w)[5]);
auto priority = bool(features(w)[5]);
auto priority = bool{features(w)[5]};
ナンバーワンは今でも私のお気に入りです。入力が少なく、他の 3 つと同じくらい明確です。
保証された初期化に関するポイントは、実際には当てはまりません。変数を何らかの方法で初期化する前ではなく、変数を宣言しているためです。狭小化に関するもう 1 つの議論は、簡単なテストではうまくいきませんでした。