Możesz obejść się bez nagłówka:
using size_t = decltype(sizeof(int));
using size_t = decltype(sizeof 1);
using size_t = decltype(sizeof "anything");
Dzieje się tak, ponieważ standard C ++ wymaga:
Wynikiem sizeof
i sizeof...
jest stałą typu std::size_t
. [Uwaga: std::size_t
jest zdefiniowane w standardowym nagłówku <cstddef>
(18.2). - notatka końcowa]
Innymi słowy, norma wymaga:
static_assert(std::is_same<decltype(sizeof(int)), std::size_t>::value,
"This never fails.");
Zauważ również, że jest całkowicie w porządku, aby uczynić tę typedef
deklarację w globalnej i std
przestrzeni nazw, o ile pasuje ona do wszystkich innych typedef
deklaracji o tej samej nazwie typu (w przypadku niezgodnych deklaracji jest generowany błąd kompilatora).
To dlatego, że:
§7.1.3.1 Nazwa typedef-name nie wprowadza nowego typu, tak jak deklaracja klasy (9.1) lub deklaracja wyliczenia.
§7.1.3.3 W podanym zakresie nieklasowym typedef
specyfikator może być użyty do przedefiniowania nazwy dowolnego typu zadeklarowanego w tym zakresie w celu odniesienia się do typu, do którego już się odnosi.
Sceptykom, którzy twierdzą, że jest to dodanie nowego typu do przestrzeni nazw std
, a takie działanie jest wprost zabronione przez standard, a to jest UB i to wszystko; Muszę powiedzieć, że takie podejście sprowadza się do ignorowania i zaprzeczania głębszemu zrozumieniu podstawowych kwestii.
Standard zabrania dodawania nowych deklaracji i definicji do przestrzeni nazw, std
ponieważ w ten sposób użytkownik może narobić bałaganu w bibliotece standardowej i odstrzelić sobie całą nogę. Standardowym autorom łatwiej było pozwolić użytkownikowi wyspecjalizować się w kilku konkretnych rzeczach i zakazać robienia czegokolwiek innego na miarę, zamiast blokować każdą rzecz, której użytkownik nie powinien robić i ryzykować, że przegapi coś ważnego (i tę nogę). Zrobili to w przeszłości, gdy wymagali, aby żaden standardowy kontener nie był tworzony z niekompletnym typem, podczas gdy w rzeczywistości niektóre kontenery mogą to zrobić (zobacz The Standard Librarian: Containers of Incomplete Types, Matthew H. Austern ):
... Ostatecznie wszystko wydawało się zbyt mętne i zbyt słabo zrozumiane; komisja normalizacyjna uważała, że nie ma innego wyboru niż stwierdzenie, że kontenery STL nie powinny działać z niekompletnymi typami. Na wszelki wypadek zastosowaliśmy ten zakaz również do reszty biblioteki standardowej.
... Z perspektywy czasu, teraz, gdy technologia jest lepiej rozumiana, ta decyzja wydaje się zasadniczo słuszna. Tak, w niektórych przypadkach możliwe jest zaimplementowanie niektórych standardowych kontenerów, aby można było tworzyć ich instancje z niekompletnymi typami - ale jest również jasne, że w innych przypadkach byłoby to trudne lub niemożliwe. W większości przypadków był to przypadek, że pierwszy test, który wypróbowaliśmy std::vector
, okazał się jednym z łatwych przypadków.
Biorąc pod uwagę, że zasady języka wymagają, std::size_t
aby być dokładnie decltype(sizeof(int))
, robienie namespace std { using size_t = decltype(sizeof(int)); }
jest jedną z tych rzeczy, które niczego nie psują.
Przed C ++ 11 nie było, decltype
a zatem nie ma możliwości zadeklarowania typu sizeof
wyniku w jednej prostej instrukcji bez angażowania dużej liczby szablonów. size_t
aliasy różnych typów na różnych architekturach docelowych, jednak nie byłoby eleganckim rozwiązaniem dodanie nowego typu wbudowanego tylko dla wyniku działania programu sizeof
i nie ma standardowych wbudowanych definicji typów. Stąd najbardziej przenośnym rozwiązaniem w tamtym czasie było umieszczenie size_t
aliasu typu w jakimś określonym nagłówku i udokumentowanie tego.
W C ++ 11 jest teraz sposób na zapisanie tego dokładnego wymagania standardu jako jednej prostej deklaracji.