Complie-time коллекция всех значений enum'a

anton.paymyshev
anton.paymyshev
enum class Color
{
	Red, Green, Blue
};

void f()
{
	static_assert(std::foo<Color>().size() == 3);
	static_assert(std::foo<Color>()[0] == Color::Red);
	static_assert(std::foo<Color>()[1] == Color::Green);
	static_assert(std::foo<Color>()[2] == Color::Blue);
}

 

5
рейтинг
5 комментариев
Victor Gubin
По идее и сейчас можно через tuple сделать, но не особо удобно

#include <tuple>
#include <type_traits>
#include <iomanip>
#include <iostream>


enum class color {
red, green, blue
};

template<typename E>
constexpr std::size_t enum_to_idx(E e) {
static_assert( std::is_enum<E>::value );
return static_cast< std::size_t > ( e );
}

static void print_rgb(const char* log_msg, uint32_t rgb)
{
std::cout << log_msg << "0x" << std::setfill('0') << std::setw(6) << std::hex << rgb << '\n';
}

int main()
{

constexpr auto aarr = std::make_tuple(
std::make_pair(color::red, 0xFF0000U),
std::make_pair(color::green, 0x00FF00U),
std::make_pair(color::blue, 0x0000FFU) );
typedef decltype(aarr) enum_av_aray;

static_assert( 3 == std::tuple_size<enum_av_aray>::value );
static_assert( color::red == std::get<0>( aarr ).first );
static_assert( color::green == std::get<1>( aarr ).first );
static_assert( color::blue == std::get<2>( aarr ).first );


std::cout << "Compile time associative array size: " << std::tuple_size<enum_av_aray>::value << '\n' << std::endl;

print_rgb("\t RED color value: ", std::get< enum_to_idx(color::red) >( aarr ).second );
print_rgb("\t GREEN color value: ", std::get< enum_to_idx(color::green) >(aarr).second);
print_rgb("\t BLUE color value: ", std::get< enum_to_idx(color::blue) >(aarr).second );

std::cout.flush();

return 0;
}
Victor Gubin
Antervis
ждите метаклассы от Герба Саттера
Antervis
anton.paymyshev
Victor Gubin,
>> constexpr auto aarr = std::make_tuple(
>> std::make_pair(color::red, 0xFF0000U),
>> std::make_pair(color::green, 0x00FF00U),
>> std::make_pair(color::blue, 0x0000FFU) );

этот способ предполагает что нужно *помнить* поддерживать список значений enum именно в двух местах, а этого как раз этого хотелесь бы избежать.

Как раз для того чтобы не забыть обновить aarr новым элеменотм enum'a "yellow", можно было было бы написать:
static_assert(std::foo<color>().size() == aarr.size());
и получить ошибку 4 != 3
anton.paymyshev
Victor Gubin
Поддерживаю. Использовать tuple, как есть неудобно.

К тому-же весь алгоритм разваливается если скажем:

enum class color: uint8_t {
red = 0x04, green = 0x02, blue = 0x01
}

Нужна полноценная рефлексия на этапе компиляции, что-бы можно было пройтись по всем константам enum-а.
Victor Gubin
Antervis
Victor Gubin, хорошо бы и возможность пройтись по именам значений enum'ов/классов/пр.
Antervis
Другие идеи
Группа создана, чтобы собирать предложения к стандарту C++, организовывать их внутренние обсуждения, помогать готовить их для отправки в комитет и защищать на общих собраниях в рабочей группе по С++ Международной организации по стандартизации (ISO).