Typ piszący teoretycznie void
to, co nazywa się w innych językach unit
lub top
. Jego logicznym odpowiednikiem jest Prawda . Każda wartość może być legalnie przypisana void
(każdy typ jest podtypem void
). Pomyśl o tym jako o zestawie „wszechświata”; nie ma wspólnych operacji dla wszystkich wartości na świecie, więc nie ma prawidłowych operacji na wartości typu void
. Mówiąc inaczej, mówiąc, że coś należy do zestawu wszechświata, nie daje żadnych informacji - już to wiesz. Tak więc dźwięk jest następujący:
(void)5;
(void)foo(17); // whatever foo(17) does
Ale poniższe zadanie nie jest:
void raise();
void f(int y) {
int x = y!=0 ? 100/y : raise(); // raise() returns void, so what should x be?
cout << x << endl;
}
[[noreturn]]
Z drugiej strony, nazywa się czasami empty
, Nothing
, Bottom
lub Bot
i jest logicznym odpowiednikiem fałszywy . Nie ma w ogóle żadnych wartości, a wyrażenie tego typu można rzutować na dowolny typ (tj. Jest podtypem). To jest pusty zestaw. Zauważ, że jeśli ktoś powie ci „wartość wyrażenia foo () należy do pustego zestawu”, jest to bardzo pouczające - mówi ci, że to wyrażenie nigdy nie zakończy normalnego wykonania; przerwie, rzuci lub zawiesi się. Jest to dokładne przeciwieństwo void
.
Poniższe nie ma więc sensu (pseudo-C ++, ponieważ noreturn
nie jest to typ pierwszej klasy C ++)
void foo();
(noreturn)5; // obviously a lie; the expression 5 does "return"
(noreturn)foo(); // foo() returns void, and therefore returns
Ale poniższe przypisanie jest całkowicie uzasadnione, ponieważ throw
kompilator rozumie, że nie zwraca:
void f(int y) {
int x = y!=0 ? 100/y : throw exception();
cout << x << endl;
}
W idealnym świecie możesz użyć noreturn
jako wartości zwracanej dla raise()
powyższej funkcji :
noreturn raise() { throw exception(); }
...
int x = y!=0 ? 100/y : raise();
Niestety C ++ na to nie pozwala, prawdopodobnie ze względów praktycznych. Zamiast tego daje możliwość użycia [[ noreturn ]]
atrybutu, który pomaga kierować optymalizacjami kompilatora i ostrzeżeniami.