W przykładzie Stroustrupa, co oznacza dwukropek w wyrażeniu „powrót 1: 2”?

163

Nie rozumiem jednego konkretnego zastosowania okrężnicy.

Znalazłem to w książce The C ++ Programming Language Bjarne Stroustrup, wydanie 4, sekcja 11.4.4 „Call and Return”, strona 297:

void g(double y)
{
  [&]{ f(y); }                                               // return type is void
  auto z1 = [=](int x){ return x+y; }                        // return type is double
  auto z2 = [=,y]{ if (y) return 1; else return 2; }         // error: body too complicated
                                                             // for return type deduction
  auto z3 =[y]() { return 1 : 2; }                           // return type is int
  auto z4 = [=,y]()−>int { if (y) return 1; else return 2; } // OK: explicit return type
}

Mylący dwukropek pojawia się w linii 7 w oświadczeniu return 1 : 2. Nie mam pojęcia, co to może być. To nie jest etykieta ani operator trójskładnikowy.

Wydaje się, że jest to warunkowy operator trójskładnikowy bez pierwszego elementu członkowskiego (i bez ?), ale w takim przypadku nie rozumiem, jak mógłby działać bez warunku.

Piockñec
źródło
6
To błąd kompilacji po mojej stronie (gcc i clang). Ponadto wszystkie te wiersze wymagają średników, ale nadal zawierają błąd.
Cruz Jean
216
Uwaga moderatora: Przed oddaniem głosu proszę bardzo uważnie pomyśleć o zamknięciu tego pytania jako „literówki”. Tak, problem to literówka, ale to nie jest literówka, którą popełnił pytający. Raczej jest to znalezione w opublikowanej książce. Oznacza to, że to pytanie i odpowiedzi na nie mogą być przydatne dla innych w przyszłości, co jest silnym przeciwwskazaniem do zamknięcia go jako literówki. (AKTUALIZACJA: Ten temat jest obecnie omawiany w Meta ; prosimy o rozważenie tego.)
Cody Gray
3
Być może najlepszą odpowiedzią byłoby: Spróbuj skompilować kod; jeśli się nie kompiluje, to dobra wskazówka, że ​​jest to literówka.
jrw32982 obsługuje Monikę
Przychodzi mi do głowy wiele przykładów, które nie potrafią się skompilować (lub nawet powodują wewnętrzny błąd kompilatora) na jednym kompilatorze, ale są akceptowane bez problemu na innym
J. Antonio Perez
1
@John Właśnie wypróbowałem kilka wyrażeń zwiniętych z MSVC i nie skompilowały się. Więc wyraźnie cały rozdział, który właśnie przeczytałem, musi być literówką? ;) Kompilatory C ++ nie potrafią kompilować poprawnego kodu C ++ przez cały czas, wynika to z absurdalnie skomplikowanego języka.
Voo

Odpowiedzi:

205

To literówka w książce. Spójrz na Errata dla drugiego i trzeciego wydruku języka programowania C ++ . Przykład musi wyglądać jak poniżej:

auto z3 =[y]() { return (y) ? 1 : 2; }
SM
źródło
11
Dlaczego (y)i nie tylko y?
Mały pomocnik
7
@LittleHelper Być może to najlepsza praktyka lub coś w tym stylu, zawsze widzę, że jest to napisane w ten sposób. Może żeby uniknąć nieporozumień z bardziej skomplikowanymi porównaniami ...
Redwolf Programs
28
Osobiście często używam (cond) ? a : bdla jasności - pomaga mi to uniknąć błędnego odczytania np. Instrukcji, foo = x > y ? a : bjak foo = x ...przy przeglądaniu kodu.
user1686
8
@LittleHelper To nie jest tam naprawdę potrzebne. Jednak w makrze podobnym do funkcji najlepszą praktyką jest umieszczanie nawiasów wokół argumentów, w których są używane, ponieważ w przeciwnym razie rozwinięcie argumentów może spowodować nieoczekiwane zachowanie. Rozważmy makro funkcyjne, które podwoi wartość „foo (x) x * 2”, gdy wywołasz je za pomocą „foo (2 + 3)”. Wynik będzie 2+ (3 * 2), ponieważ argument jest rozwijany bez zmian, a pierwszeństwo przejmują reguły. Jeśli Twoje makro to „foo (x) (x) * 2”, to poprawnie otrzymasz (2 + 3) * 2. Być może Stroustrup ma zwyczaj używania tego stylu wszędzie ze względu na bezpieczeństwo kodowania.
Graham
2
@Graham Bardzo mało prawdopodobne. Stroustrup zasadniczo nie pisze makr funkcyjnych (funkcje wbudowane w C ++ są lepsze). O wiele bardziej prawdopodobne jest, że operator trójskładnikowy ma nieco skomplikowane reguły pierwszeństwa, dlatego dobrze jest zwykle wyjaśniać pierwszeństwo za pomocą parens.
Martin Bonner wspiera Monikę
19

Wygląda mi na zwykłą literówkę. Prawdopodobnie powinno być:

auto z3 =[y]() { return y ? 1 : 2; }

Zauważ, że ponieważ lambda nie przyjmuje żadnych parametrów, pareny są opcjonalne. Możesz użyć tego zamiast tego, jeśli wolisz:

auto z3 =[y] { return y ? 1 : 2; }
Jerry Coffin
źródło
11

return 1 : 2; jest błędem składniowym, to nieprawidłowy kod.

return (y) ? 1 : 2;Zamiast tego poprawne stwierdzenie byłoby bardziej podobne .

Remy Lebeau
źródło