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 sizeofi sizeof...jest stałą typu std::size_t. [Uwaga: std::size_tjest 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ę typedefdeklarację w globalnej i stdprzestrzeni nazw, o ile pasuje ona do wszystkich innych typedefdeklaracji 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 typedefspecyfikator 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, stdponieważ 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_taby 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, decltypea zatem nie ma możliwości zadeklarowania typu sizeofwyniku w jednej prostej instrukcji bez angażowania dużej liczby szablonów. size_taliasy 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 sizeofi nie ma standardowych wbudowanych definicji typów. Stąd najbardziej przenośnym rozwiązaniem w tamtym czasie było umieszczenie size_taliasu 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.