Как определить настраиваемый кросс-платформенный тип size_t?
std::size_t
обычно используется для индексирования массива и подсчета циклов. По определению std::size_t
- это целочисленный тип без знака результата оператора sizeof
, а также оператор sizeof...
и alignof
(начиная с С++ 11). Он определен в следующих заголовках:
-
<cstddef>
-
<cstdio>
-
<cstdlib>
-
<cstring>
-
<ctime>
-
<cwchar>
Насколько я понимаю, тип, возвращаемый этими операторами, определяется при реализации.
Я хочу определить пользовательский size_t
, чтобы избежать вытаскивания ненужных материалов из любого из заголовков, упомянутых выше, в файл .cpp
, так как в моем файле мне нужно только std::size_t
.
В С++ 11 и выше я думал, что могу использовать следующий псевдоним:
using size_t = decltype(sizeof(1));
Однако я хотел бы определить тип size_t
для компиляторов pre-С++ 11 в переносном/межплатформенном виде.
Итак, есть ли переносимый способ определить size_t
для pre-С++ 11?
Ответы
Ответ 1
Хорошо теоретически, если листинг всех возможных (неподписанных) кандидатов для size_t
не беспокоит вас, вы можете использовать SFINAE:
template <class T, class N = void, bool = sizeof(T) == sizeof(sizeof(T))>
struct TL {
typedef typename N::type type;
};
template <class T, class N>
struct TL<T, N, true> {
typedef T type;
};
typedef TL<unsigned short,TL<unsigned int, TL<unsigned long, TL<unsigned long long> > > >::type SizeT;
[live demo]
Edit:
Обходной путь для компиляторов, которые отличаются unsigned long
от unsigned long long
, несмотря на то, что они принимают sizeof(unsigned long) == sizeof(unsigned long long)
:
template <class U>
U *declptrval(U);
template <class U>
char is_exact(U *);
template <class U>
short is_exact(...);
template <class T, class N = void, bool = sizeof(is_exact<T>(declptrval(sizeof(T))))==sizeof(char)>
struct TL {
typedef typename N::type type;
};
template <class T, class N>
struct TL<T, N, true> {
typedef T type;
};
typedef TL<unsigned short,TL<unsigned int, TL<unsigned long, TL<unsigned long long> > > >::type SizeT;
[live demo]
Ответ 2
Насколько я знаю, вы указали только два кросс-платформенных способа получить size_t
: включить определение из стандартного заголовка или decltype (начиная с С++ 11). Но оба они явно недоступны вам.
Третий вариант - ручной портирование, т.е. использование заранее определенных макросов для обнаружения среды и выбор правильного typedef из списка ручных команд typedefs. Например, в GCC вы можете использовать __SIZE_TYPE__
(однако рассмотрите предупреждение в документации о том, что макрос не должен использоваться напрямую и что он не предоставляется на всех платформах). В других компиляторах вы должны использовать что-то еще.
Ответ 3
К сожалению, "определяемый реализацией" включает файлы заголовков, а не только сам компилятор. Если вы посмотрите на [expr.sizeof], они, кажется, предлагают просто использовать это:
#include <cstddef>