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.


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; }

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; }

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 .

Korzystając z naszej strony potwierdzasz, że przeczytałeś(-aś) i rozumiesz nasze zasady używania plików cookie i zasady ochrony prywatności.
Licensed under cc by-sa 3.0 with attribution required.