Можно было обойтись без заголовка:
using size_t = decltype(sizeof(int));
using size_t = decltype(sizeof 1);
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объявлениям того же typedef-name (при несоответствующих объявлениях выдается ошибка компилятора).
Это потому что:
§7.1.3.1 typedef-name не вводит новый тип в отличие от объявления класса (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, а стандартные встроенные определения типов отсутствуют. Следовательно, наиболее переносимым решением в то время было поместить size_tпсевдоним типа в какой-то определенный заголовок и задокументировать его.
В C ++ 11 теперь есть способ записать это точное требование стандарта в виде одного простого объявления.