Как элегантно поместить все перечисления в std::set

У меня есть перечисление, и я хочу поместить их все в набор (а затем удалить некоторые с помощью алгоритма set_intersection, но это оффтоп). Все отлично работает, за исключением того, что я застрял на шаге 1. :)

Если у меня есть (у реального класса есть перечисление с более высокой кардинальностью)

class MyClass
{
enum Color{red, green , blue}
};

Как бы я инициировал std::set<MyClass::Color>, чтобы он содержал все перечисления.
Очевидно, я могу вручную вставлять их один за другим, выполнять цикл for с приведением, поскольку они идут последовательно и начинаются с 0 (я думаю, что это необходимо, если я не использую = в enum определение), но я ищу более элегантный способ.

РЕДАКТИРОВАТЬ: я предпочитаю решение С++ 03, если это возможно, потому что текущий экземпляр проблемы требует этого, но если нет, С++ 11 тоже полезно знать.


person NoSenseEtAl    schedule 14.03.2013    source источник
comment
если они идут подряд и начинаются с нуля, вы можете добавить total в качестве последнего элемента перечисления, значение которого становится равным количеству значений =)   -  person kassak    schedule 14.03.2013
comment
Хорошее замечание от @kassak total или colors_count как последний элемент перечисления очень полезно во многих случаях   -  person borisbn    schedule 14.03.2013
comment
@kassak Я знаю об этом трюке, но он зависит от комментариев CAPS LOCK, не позволяющих людям перейти и определить значение int для каждого перечисления. :)   -  person NoSenseEtAl    schedule 14.03.2013


Ответы (3)


Это вариант:

#define COLORS {red, green , blue}
enum Color COLORS;
static std::set<Color> color_set() {
    return COLORS;
}
#undef COLORS
person Pubby    schedule 14.03.2013
comment
@NoSenseEtAl Да, списки инициализаторов. - person Pubby; 14.03.2013
comment
Я отредактировал вопрос, чтобы сказать, что я предпочитаю 03, если это возможно, но если это единственный хороший способ сделать это, я приму ваш ответ. Извините, что не упомянул об этом в начальном вопросе. :) - person NoSenseEtAl; 14.03.2013
comment
Если у вас нет списков инициализаторов, вы можете сделать что-то вроде Color colors[] = COLORS; return std::set<Color>(colors, colors + sizeof(colors) / sizeof(*colors)); - person Steve Jessop; 14.03.2013
comment
@NoSenseEtAl в 03 вы можете определить без фигурных скобок, а затем передать список, разделенный запятыми, для повышения назначения - person kassak; 14.03.2013
comment
@SteveJessop ах, старая добрая инициализация массива контейнеров STL :) tnx - person NoSenseEtAl; 14.03.2013
comment
@SteveJessop Я бы добавил static перед Color colors[] = COLORS; - person borisbn; 14.03.2013
comment
@borisbn: если хочешь. Я не думаю, что это имеет большое значение: каждый вызов этой функции создает set, поэтому мне все равно, инициализирует ли он также каждый раз массив :-) - person Steve Jessop; 14.03.2013
comment
На мой взгляд, любое решение, использующее #define, по определению неэлегантно. Я считаю, что этот код значительно менее элегантен, чем вариант цикла, отклоненный ОП. - person Jack Aidley; 14.03.2013
comment
@JackAidley: #define часто неэлегантны, потому что их очень трудно читать. Но в данном случае я думаю, что это действительно легко читать, а результирующий код очень короткий и лаконичный. - person Nicu Stiurca; 16.03.2013

Используйте std::bitset< total_colors >. Это более подходящая структура данных для множества на конечном пространстве. Каждому цвету соответствует логическое значение, указывающее, является ли он частью набора. Вы можете инициализировать его для всех true, используя my_bitset.set().

person Potatoswatter    schedule 14.03.2013

Лично я бы использовал цикл и просто бросал вещи по ходу дела.

Однако, если вы настроены против приведения типов, вы можете определить операторы в перечислении, чтобы вы могли перебирать их, используя ++. Таким образом, вы можете зацикливаться без литья.

person Jack Aidley    schedule 14.03.2013
comment
Что ж, определение ++ будет содержать приведение. - person Potatoswatter; 14.03.2013
comment
Да, но петля не будет. Вы будете иметь дело с интерфейсом, который скрывает неприятные детали. - person Jack Aidley; 14.03.2013