web-dev-qa-db-ja.com

auto x {3}がinitializer_listを推定するのはなぜですか?

C++ 11ではautoが大好きです。素晴らしいです。しかし、私はいつもつまずくので、それは本当に私の神経質になる不整合があります。

int i = 3;       // i is an int with value 3
int i = int{3};  // i is an int with value 3
int i(3);        // i is an int with value 3 (possibly narrowing, not in this case)
int i{3};        // i is an int with value 3

auto i = 3;      // i is an int with value 3
auto i = int{3}; // i is an int with value 3
auto i(3);       // i is an int with value 3
auto i{3};       // wtf, i is a std::initializer_list<int>?!

この奇妙な振る舞いは、初心者にとっては混乱を招き、経験豊富なユーザーにとっては煩わしいものです。C++には、一貫性とコーナーケースが十分にあり、現状のままにしておく必要があります。標準委員会がこのケースで新しいものを導入することを決定した理由を誰かが説明できますか?

タイプstd::initializer_listの変数を宣言することが有用または頻繁に行われるものである場合は、それを理解できましたが、私の経験では、それはほとんど意図的なものではありません。

std::initializer_list<int> l{3};
auto l = std::initializer_list<int>{3};
auto l = {3}; // No need to specify the type

うまくいきます。では、auto x{i}の特別なケースの背後にある理由は何ですか?

57
Tristan Brindle

長い話を短くするには:

  • ブレース付きの初期化式{}自体には型がありません
  • autoは型情報を推測する必要があります
  • int{3}は明らかに「初期化リストから取得した値でint varを作成する」ことを意味します。したがって、その型はintであり、より広いコンテキストで使用できます(int i = int{3}は機能し、auto i = int{3}は型を推定できます。右側が明らかにintであるためです)
  • {3}自体にはタイプがありません(それはca n't be intです。これはvalueではなくイニシャライザリスト)、つまりautoは機能しません—ただし、委員会はautoがこの場合でも機能するはずであると考えたため、「最良の」と判断しました(ええ、定義によりタイプレスです)初期化リストのタイプは... std::initializer_list、おそらくご想像のとおり。

しかし、ご指摘のとおり、これによりautoの動作全体が意味的に一貫しなくなりました。それが、委員会に提出された、つまりN3681N3912およびN3922を変更する提案があった理由です。この問題に関する委員会の合意がないため、以前の提案はFI3として却下されました http://isocpp.org/files/papers/n3852.html#FI 、現在(N3922 )取得 採用 2015年の第1四半期 ;

tl; dr標準準拠コンパイラ1最先端のC++サポートあり)2 は、新しい、より健全なセマンティクスをすでに備えているか、まもなく提供する予定です。

標準化委員会はN3922をドラフトC++ 17に採用することで問題を認めました。

- っていうことは

auto x1 = { 1, 2 }; // decltype(x1) is std::initializer_list<int>
auto x2 = { 1, 2.0 }; // error: cannot deduce element type
auto x3{ 1, 2 }; // error: not a single element
auto x4 = { 3 }; // decltype(x4) is std::initializer_list<int>
auto x5{ 3 }; // decltype(x5) is int

今、良くも悪くも。

参考文献:

http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2013/n3681.html

http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2014/n3912.html

http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2014/n3922.html

http://scottmeyers.blogspot.com/2014/03/if-braced-initializers-have-no-type-why.html

http://herbsutter.com/2014/11/24/updates-to-my-trip-report/


1GCC 5.1(およびそれ以上) C++ 11/C++ 14モードでもN3922を使用しているようです

2Clang 3.8、警告付き

これは下位互換性のない変更であり、(C++委員会の要求に従って)autoからの型の推定を許可するすべての言語バージョンに適用されます。

41
vaxquis