2014-09-01 12 views
46

Uwielbiam auto w C++ 11. To jest wspaniałe. Ale ma jedną niespójność, która naprawdę działa mi na nerwy, bo potknięcie się o niego cały czas:Dlaczego auto x {3} dedukuje listę initializer_list?

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>?! 

To dziwne zachowanie jest mylące dla początkujących i irytujące dla doświadczonych użytkowników - C++ ma dość drobne nieścisłości i ziemię przypadki, o których należy pamiętać tak jak jest. Czy ktoś może wyjaśnić, dlaczego komitet ds. Norm postanowił wprowadzić w tym przypadku nowy?

Mogłem to zrozumieć, jeśli zadeklarowanie zmiennej o typie std::initializer_list było czymś, co było przydatne lub robione często, ale z mojego doświadczenia wynika, że ​​prawie nigdy nie było celowe - aw rzadkich przypadkach, gdy tego chciałeś, każdy z

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

będzie działać dobrze. Więc jaki jest powód specjalnego przypadku dla auto x{i}?

+14

To właśnie dlatego [zasada ulegnie zmianie] (http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2014/n3922.html). –

+1

Powiązane: http://stackoverflow.com/q/17582667 – dyp

+1

Rozwiązanie: nie używaj automatycznego dla żadnego z tych przypadków (z wyjątkiem # 2). :-) – dlf

Odpowiedz

33

Aby długie opowiadanie:

  • usztywnione wyrażenie initializer {} ma typ sama
  • auto musi wywnioskować informacje typu
  • int{3} oczywiście znaczy „stworzyć int var z wartości pobranej od lista inicjalizująca ", więc jego typ to tylko int i może być używany w szerszym kontekście (int i = int{3} zadziała, a auto i = int{3} może wydedukować typ, ponieważ prawa strona jest oczywiście Typ int)
  • {3} sam typ (nie ma to nie może być int, ponieważ nie jest to wartość ale lista initializer), więc auto nie będzie działać - ale, ponieważ komisja uznała, że auto powinny nadal działać w tym przypadku, zdecydowali, że "najlepszy" typ dla (tak, bez typów z definicji) lista inicjalizatorów byłaby ... std::initializer_list, jak już pewnie się domyśliliście.

Ale, jak zauważyłeś, to sprawiło, że całe zachowanie auto było dość niespójne semantycznie. Dlatego pojawiły się propozycje zmian - mianowicie: N3681, N3912 i N3922 - złożony do komisji. Dawna propozycja została ODRZUCONA jako FI3 ze względu na brak konsensusu komisji w tej sprawie, http://isocpp.org/files/papers/n3852.html#FI3, aktualny (N3922) otrzymał adopted ca. Q1 of 2015;

tl; dr można zakładać, że standards-compliant compilers1 z bleeding-edge C++ support2 albo mają nowe, bardziej sane-owski semantykę już na miejscu, albo będzie musiał go wkrótce.

Komitet Normalizacyjny potwierdził problem, przyjmując N3922 do wersji C++ 17.

- dlatego

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 

teraz, lepiej lub gorzej.

Dalsze informacje:

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/


GCC 5,1 (& się) apparently uses N3922 even in C++11/C++14 mode

Clang 3,8, z zastrzeżeniem,

Jest to niezgodne wstecz zmiana, którą stosuje się do wszystkich wersji językowych zezwalaj na odliczanie typów z auto (na żądanie komitetu C++).

+2

N3922 został przyjęty ponad rok temu (listopad 2014 r., w Urbana) –

+0

@TC bardzo dziękuję za zauważenie tego - i dziwne, że nikt o tym nie wspomniał wcześniej! – vaxquis

+0

@vaxquis Czy wiecie, kiedy to zostanie zaakceptowane i zastosowane do większości kompilatorów, takich jak g ++ i clang? – Curious

Powiązane problemy