Ви можете обійтися без заголовка:
using size_t = decltype(sizeof(int));
using size_t = decltype(sizeof 1); // The shortest is my favourite.
using size_t = decltype(sizeof "anything");
Це тому, що стандарт C ++ вимагає:
Результатом sizeof
і sizeof...
є константа типу std::size_t
. [Примітка: std::size_t
це визначено у стандартному заголовку <cstddef>
(18.2). - кінцева примітка]
Іншими словами, стандарт вимагає:
static_assert(std::is_same<decltype(sizeof(int)), std::size_t>::value,
"This never fails.");
Також зауважте, що цілком нормально робити це typedef
оголошення в глобальному та std
просторі імен, якщо воно відповідає всім іншим typedef
оголошенням того самого типуdef-name (помилка компілятора видається в невідповідних оголошеннях).
Це відбувається тому:
§7.1.3.1 Ім'я typedef не вводить новий тип так, як це робить декларація класу (9.1) або декларація enum.
§7.1.3.3 У даному некласовому діапазоні typedef
специфікатор може бути використаний для перевизначення імені будь-якого типу, оголошеного в цій області, для посилання на тип, на який він уже посилається.
Скептикам, які стверджують, що це означає додавання нового типу до простору імен std
, і такий вчинок категорично заборонений стандартом, і це UB, і все, що до цього стосується; Я повинен сказати, що таке ставлення означає ігнорування та заперечення глибшого розуміння основних питань.
Стандарт забороняє додавати нові декларації та визначення у простір імен, std
оскільки таким чином користувач може зіпсувати стандартну бібліотеку і вистрілити всю ногу. Для стандартних авторів було простіше дозволити користувачеві спеціалізуватися на декількох конкретних речах і заборонити робити що-небудь інше з гарною мірою, ніж забороняти кожну річ, яку користувач не повинен робити, і ризикувати пропустити щось важливе (і цю ногу). Вони робили це раніше, коли вимагали, щоб жоден стандартний контейнер не був створений з неповним типом, тоді як насправді деякі контейнери могли б це зробити (див. «Стандартний бібліотекар: Контейнери неповних типів» від Метью Х. Остерна ):
... Врешті-решт, все це здавалося занадто каламутним і занадто погано зрозумілим; Комітет стандартизації не думав, що є будь-який вибір, окрім як сказати, що контейнери STL не повинні працювати з неповними типами. Для гарної міри ми застосували цю заборону і до решти стандартної бібліотеки.
... Ретроспективно, тепер, коли технологію краще зрозуміли, це рішення все ще здається в основному правильним. Так, в деяких випадках можливо реалізувати деякі стандартні контейнери, щоб їх можна було створити з неповними типами - але також очевидно, що в інших випадках це буде важко або неможливо. Це був здебільшого шанс, що перший тест, який ми спробували, використовуючи std::vector
, виявився одним із найпростіших випадків.
Враховуючи, що мовні правила вимагають std::size_t
бути точно decltype(sizeof(int))
, робити namespace std { using size_t = decltype(sizeof(int)); }
це одна з речей, яка нічого не порушує.
До C ++ 11 не було decltype
і, отже, жодного способу оголосити тип sizeof
результату в одному простому твердженні, не задіявши велику кількість шаблонів. size_t
псевдоніми різних типів на різних цільових архітектурах, однак, не було б елегантним рішенням додати новий вбудований тип лише для результату sizeof
, і немає стандартних вбудованих typedefs. Отже, найбільш портативним рішенням на той час було помістити size_t
псевдонім типу в якийсь конкретний заголовок і документувати це.
У C ++ 11 тепер є спосіб записати цю точну вимогу стандарту як одну просту декларацію.