enum class A {
a0=0, a3=3, a4=4
};
constexpr std::array<A, 3> ALL_A {A::a0, A::a3, A::a4}; // constexpr is important here
for(A a: ALL_A) {
if(a==A::a0 || a==A::a4) std::cout << static_cast<int>(a);
}
A constexpr std::array
может выполнять итерации даже непоследовательных перечислений без создания экземпляра массива компилятором. Это зависит от таких вещей, как эвристика оптимизации компилятора и от того, берете ли вы адрес массива.
В моих экспериментах я обнаружил, что g++
9.1 с -O3
оптимизирует вышеприведенный массив, если есть 2 непоследовательных значения или довольно много последовательных значений (я проверял до 6). Но он делает это только в том случае, если у вас есть оператор if
. (Я пробовал оператор, который сравнивал целочисленное значение больше, чем все элементы в последовательном массиве, и он включал итерацию, хотя ни один из них не был исключен, но когда я пропустил оператор if, значения были помещены в память.) значения из непоследовательного перечисления в [одном случае | https://godbolt.org/z/XuGtoc]. Я подозреваю, что это странное поведение связано с глубокой эвристикой, связанной с кэшем и предсказанием ветвлений.
Вот ссылка на простую тестовую итерацию для godbolt , демонстрирующую, что массив не всегда создается.
Ценой этой техники является написание элементов enum дважды и синхронизация двух списков.