В ответ на предыдущий вопрос SO " Enumerate over enum в C ++ " я предложил следующее многократно используемое решение, которое использует type-safe enum idiom . Мне просто любопытно увидеть отзывы сообщества о моем решении. В этом решении используется статический массив, который перед первым использованием заполняется с помощью безопасных типов перечислимых объектов. Итерация по перечислениям тогда просто сводится к итерации по массиву. Мне известно о том, что это решение не будет работать, если счетчики не увеличиваются строго.
template<typename def, typename inner = typename def::type>
class safe_enum : public def
{
typedef typename def::type type;
inner val;
static safe_enum array[def::end - def::begin];
static bool init;
static void initialize()
{
if(!init) // use double checked locking in case of multi-threading.
{
unsigned int size = def::end - def::begin;
for(unsigned int i = 0, j = def::begin; i < size; ++i, ++j)
array[i] = static_cast<typename def::type>(j);
init = true;
}
}
public:
safe_enum(type v = def::begin) : val(v) {}
inner underlying() const { return val; }
static safe_enum * begin()
{
initialize();
return array;
}
static safe_enum * end()
{
initialize();
return array + (def::end - def::begin);
}
bool operator == (const safe_enum & s) const { return this->val == s.val; }
bool operator != (const safe_enum & s) const { return this->val != s.val; }
bool operator < (const safe_enum & s) const { return this->val < s.val; }
bool operator <= (const safe_enum & s) const { return this->val <= s.val; }
bool operator > (const safe_enum & s) const { return this->val > s.val; }
bool operator >= (const safe_enum & s) const { return this->val >= s.val; }
};
template <typename def, typename inner>
safe_enum<def, inner> safe_enum<def, inner>::array[def::end - def::begin];
template <typename def, typename inner>
bool safe_enum<def, inner>::init = false;
struct color_def
{
enum type
{
begin, red = begin, green, blue, end
};
};
typedef safe_enum<color_def> color;
template <class Enum>
void f(Enum e)
{
std::cout << static_cast<unsigned>(e.underlying()) << std::endl;
}
int main()
{
std::for_each(color::begin(), color::end(), &f<color>);
color c = color::red;
}