Я расскажу об этой проблеме с правилами в «неполном и неполном» проекте стандарта ISO CPP n4659 . Акцент добавлен мной.
11.3.4 определяет объявления массива. Первый абзац содержит
Если присутствует константное выражение [в квадратных скобках] (8.20), оно должно быть преобразованным константным выражением типа std :: size_t [. ..].
blockquote>
std::size_t
изи определено как
[...] определяемый реализацией целочисленный тип без знака, который является достаточно большим, чтобы содержать размер в байтах любой объект.
blockquote>Поскольку он импортируется через заголовки стандартной библиотеки C, стандарт C имеет отношение к свойствам из
size_t
. Проект ISO C N2176 предписывает в 7.20.3 «минимальные максимумы», если хотите, целочисленных типов. Дляsize_t
этот максимум составляет 65535. Другими словами, 16-битныйsize_t
полностью соответствует.«Преобразованное константное выражение» определено в 8.20 / 4:
Преобразованное константное выражение типа T является выражением, неявно преобразованным в тип T, где преобразованное выражение является константным выражением, и неявная последовательность преобразования содержит только [любое из 10 различных преобразований, одно из которых касается целых чисел (пар. 4.7):]
- целочисленные преобразования (7.8) , кроме сужения преобразования (11.6.4)
blockquote>Интегральное преобразование (в отличие от повышения , которое изменяет тип на эквивалентные или более крупные типы) определяется следующим образом (7.8 / 3):
Prvalue целочисленного типа может быть преобразовано в prvalue другого целочисленного типа.
blockquote>7.8 / 5 затем исключает интегральные продвижения из интегральных преобразований. Это означает, что преобразования обычно сужают изменения типа.
Сужающие преобразования (которые, как вы помните, исключены из списка разрешенных преобразований в преобразованных константных выражениях , используемых для размеров массивов), определены в контексте списка -инициализация, 11.6.4, пар. 7
Сужающее преобразование - это неявное преобразование
blockquote>
[...]
7.3 1 sup> - из целочисленного типа [. ..] к целочисленному типу, который не может представлять все значения исходного типа, за исключением случаев, когда источником является константное выражение, значение которого после интегральных повышений будет соответствовать целевому типу.Это фактически говорит о том, что эффективный размер массива должен быть постоянным значением при отображении, что является вполне разумным требованием для избежания неожиданностей.
А теперь давайте сделаем это вместе. Рабочая гипотеза состоит в том, чтоstd::size_t
представляет собой 16-битный целочисленный тип без знака со значением в диапазоне 0,65535. Целочисленный литерал65537
не представлен в 16-битной системеunsigned int
и поэтому имеет типlong
. Поэтому он будет подвергаться целочисленному преобразованию. Это будет сужающее преобразование , потому что значение не представляется в 16-битномsize_t
2 sup>, так что условие исключения в 11.6.4 / 7.3, "значение подходит в любом случае ", не применяется.Итак, что это значит?
11.6.4 / 3.11 - это универсальное правило для сбоя при создании значения инициализатора из элемента в списке инициализатора. Поскольку правила списков инициализаторов используются для размеров массивов, мы можем предположить, что универсальное условие сбоя преобразования применяется к константе размера массива:
(3.11) - В противном случае программа плохо сформирован.
blockquote>Для создания диагностики требуется соответствующий компилятор, что он и делает. Дело закрыто.
1 sup> Да, они подразделяют абзацы.2 sup> Преобразование целочисленного значения 65537 (в любом типе, который может содержать число & mdash; здесь, вероятно, `long) в 16-битовое целое число без знака является определенной операцией. 7,8 / 2 подробностей:
Если тип назначения не имеет знака, полученное значение будет являться целочисленным наименьшим числом без знака, совпадающим с целым числом источника (по модулю 2 n sup) > где n - количество битов, используемых для представления типа без знака). [Примечание: в представлении дополнения до двух это преобразование является концептуальным, и в битовой комбинации нет изменений (если нет усечения). - конец примечания]
blockquote>Двоичное представление 65537 равно
1_0000_0000_0000_0001
, то есть установлен только младший значащий бит из младших 16 битов. Преобразование в 16-битное значение без знака (которое указывает косвенное свидетельствоsize_t
) вычисляет [значение выражения] по модулю 2 ^ 16, т. Е. Просто принимает младшие 16 бит. Это приводит к значению 1, указанному в диагностике компилятора.
Согласно этой странице документации, при попытке составить список, который является слишком большим, Вы, как предполагается, получаете a GL_OUT_OF_MEMORY
сообщение об ошибке.
удостоверьтесь, что Вы звоните glGetError()
прежде и после того, как Вы создаете список и обрабатываете все результаты до GL_NO_ERROR
возвращается.
Кажется, нет способа оценить количество команд, которые может содержать список. Это, вероятно, потому что каждая команда берет различный размер в зависимости от своих аргументов и устройства определенное используемое кодирование. Списки сохранены в видеопамяти карты поэтому при использовании относительно неархаичной карты, это не должно обычно действительно быть проблемой ни для каких довольно размерных списков. Если Вы действительно находите, что это - действительно проблема, можно, вероятно, использовать массивы Вершины или даже VBOs