С++ 11, целочисленный тип определяется диапазоном?

Итак, этот вопрос возник, выполняя довольно простое кодирование, рассмотрим следующее:

for(unsigned int x=0x00000000; x<0xFFFFFFFF; x++)
{
    // ...
}

Приведенный выше код работает, как и ожидалось, при условии, что 'sizeof(unsigned int)>= 4', однако, как мы знаем, на некоторых платформах это может быть не так, поэтому меня интересует нечто подобное;

for(RangeBasedInt<0x00000000, 0xFFFFFFFF>::type x=0x00000000; x<0xFFFFFFFF; x++)
{
    // ...
}

Где «RangeInt» — это шаблон, а «тип» — это наименьший целочисленный тип, достаточно большой для хранения диапазона значений от MINIMUM (0x00000000) до MAXIMUM (0xFFFFFFFF);

template<int MINIMUM, int MAXIMUM>
struct RangeBasedInt
{
    // Type based upon MINIMUM and MAXIMUM
    typedef /* MAGIC */ type;
};

Итак, вопрос в его простоте;

  1. Это реализовано где-то в стандартной библиотеке?
  2. Если нет, есть ли библиотека, реализующая это, или мне придется создать свою собственную на основе std::numeric_limits

person Skeen    schedule 02.08.2013    source источник


Ответы (1)


Это действительно легко реализовать самостоятельно. Так просто, я бы сказал, что это реализовано на языке:

typedef decltype(0xFFFFFFFF) RangeBasedInt;
for(RangeBasedInt x=0x00000000; x<0xFFFFFFFF; x++)
{
    // ...
}

2.14.2 [lex.icon] утверждает, что тип целочисленного литерала — это наименьший тип, который может содержать значение. Таким образом, если int может содержать 0xFFFFFFFF на вашем компьютере, RangeBasedInt может быть int. На моей машине это unsigned int.

Для этого конкретного предела (0xFFFFFFFF) стандарт гарантирует, что он может быть представлен одним из встроенных интегральных типов. ULONG_MAX должно быть не меньше 4294967295 (0xFFFFFFFF), а ULLONG_MAX должно быть не меньше 18446744073709551615 (0xFFFFFFFFFFFFFFFF).

Обновить

Я исправлен Скином по техническим вопросам. Таблица 6 в [lex.icon] на самом деле не говорит «наименьший тип». На самом деле он говорит, что если литерал является восьмеричной или шестнадцатеричной константой, то он будет первым типом в следующем списке, в котором может быть представлено его значение:

int
unsigned int
long int
unsigned long int
long long int
unsigned long long int

Далее в таблице указаны разные списки в зависимости от того, является ли литерал десятичным или нет, и имеет ли он суффикс или нет. Я определенно перефразировал, когда сказал «самый маленький». Для получения точных сведений обратитесь к фактическому стандарту, а не к ответу SO (мне или кому-либо еще). Когда я пишу это, последний черновик C++1y — N3691.

person Howard Hinnant    schedule 03.08.2013
comment
Что, если нижний предел (или оба) отрицательный, как бы вы с этим справились? - person Skeen; 03.08.2013
comment
Тогда ваша реализация RangeBasedInt усложняется. :-) Однако это становится настолько сложным, насколько вы хотите это сделать. Если у вас есть предел, выраженный в виде отрицательного числа, вы все равно можете decltype этот литерал (при условии, что это литерал) и получить целочисленный тип со знаком, который будет его представлять. Если вы хотите сделать действительно общий RangeBasedInt<Min, Max>, вы можете это сделать. В стандартной библиотеке его нет. И decltype очень поможет. - person Howard Hinnant; 03.08.2013
comment
Я не верю 2.14.2, утверждает то, что вы говорите, поправьте меня ссылкой, если я ошибаюсь. И GCC, и Clang, кажется, генерируют int для ограничений (0x0, 0xFF), где unsigned char будет наименьшим типом. (может быть несовершенство компилятора) - person Skeen; 03.08.2013
comment
2.14.2 утверждает, что; Тип целочисленного литерала является первым из соответствующего списка в таблице 6, в котором может быть представлено его значение. - Без всяких суффиксов последовательность есть; инт, длинный инт, длинный инт. - person Skeen; 03.08.2013
comment
Я обновил свой ответ в ответ на ваш комментарий и включил удобную ссылку на настоящий черновик C++1y. - person Howard Hinnant; 03.08.2013
comment
@Skeen: отрицательных целочисленных литералов не существует. -42 — это выражение, состоящее из литерала 42 с примененным к нему унарным минусом operator-. Литералы определены в разделе 2, а унарный оператор минус определен в разделе 5. - person Andrew Tomazos; 04.08.2013