mirror of
https://github.com/aantron/better-enums.git
synced 2025-12-06 16:56:42 +08:00
Removed range properties.
They can now be easily computed using the random access iterators. There appears to be a slight performance improvement.
This commit is contained in:
parent
1cfe53e827
commit
d9bd109172
56
enum.h
56
enum.h
@ -447,42 +447,6 @@ constexpr bool _namesMatchNocase(const char *stringizedName,
|
||||
|
||||
|
||||
|
||||
template <typename EnumType>
|
||||
constexpr EnumType _findMinLoop(const EnumType *values, size_t valueCount,
|
||||
size_t index, EnumType best)
|
||||
{
|
||||
return
|
||||
index == valueCount ? best :
|
||||
values[index]._value < best._value ?
|
||||
_findMinLoop(values, valueCount, index + 1, values[index]) :
|
||||
_findMinLoop(values, valueCount, index + 1, best);
|
||||
}
|
||||
|
||||
template <typename EnumType>
|
||||
constexpr EnumType _findMin(const EnumType *values, size_t valueCount)
|
||||
{
|
||||
return _findMinLoop(values, valueCount, 1, values[0]);
|
||||
}
|
||||
|
||||
template <typename EnumType>
|
||||
constexpr EnumType _findMaxLoop(const EnumType *values, size_t valueCount,
|
||||
size_t index, EnumType best)
|
||||
{
|
||||
return
|
||||
index == valueCount ? best :
|
||||
values[index]._value > best._value ?
|
||||
_findMaxLoop(values, valueCount, index + 1, values[index]) :
|
||||
_findMaxLoop(values, valueCount, index + 1, best);
|
||||
}
|
||||
|
||||
template <typename EnumType>
|
||||
constexpr EnumType _findMax(const EnumType *values, size_t count)
|
||||
{
|
||||
return _findMaxLoop(values, count, 1, values[0]);
|
||||
}
|
||||
|
||||
|
||||
|
||||
} // namespace _enum
|
||||
|
||||
|
||||
@ -571,11 +535,6 @@ constexpr const size_t _size = \
|
||||
\
|
||||
static_assert(_size > 0, "no constants defined in enum type"); \
|
||||
\
|
||||
constexpr const _Base _first = _value_array[0]; \
|
||||
constexpr const _Base _last = _value_array[_size - 1]; \
|
||||
constexpr const _Base _min = _enum::_findMin(_value_array, _size); \
|
||||
constexpr const _Base _max = _enum::_findMax(_value_array, _size); \
|
||||
\
|
||||
_ENUM_TRIM_STRINGS(__VA_ARGS__); \
|
||||
\
|
||||
constexpr const char * const _name_array[] = \
|
||||
@ -615,13 +574,6 @@ class EnumType : public _ENUM_NS(EnumType)::_Base { \
|
||||
constexpr static const char *_name = #EnumType; \
|
||||
constexpr static const size_t _size = _ENUM_NS(EnumType)::_size; \
|
||||
\
|
||||
constexpr static auto &_first = _ENUM_NS(EnumType)::_first; \
|
||||
constexpr static auto &_last = _ENUM_NS(EnumType)::_last; \
|
||||
constexpr static auto &_min = _ENUM_NS(EnumType)::_min; \
|
||||
constexpr static auto &_max = _ENUM_NS(EnumType)::_max; \
|
||||
\
|
||||
constexpr static const _Integral _span = _max._value - _min._value + 1; \
|
||||
\
|
||||
EnumType() = delete; \
|
||||
constexpr EnumType(_Enumerated value) : _Base(value) { } \
|
||||
constexpr EnumType(_ENUM_NS(EnumType)::_Base value) : _Base(value) { } \
|
||||
@ -724,8 +676,14 @@ class EnumType : public _ENUM_NS(EnumType)::_Base { \
|
||||
constexpr const EnumType operator +(EnumType::_Enumerated enumerated) \
|
||||
{ return (EnumType)enumerated; } \
|
||||
\
|
||||
namespace _enum { \
|
||||
namespace _data_ ## EnumType { \
|
||||
\
|
||||
constexpr const EnumType operator +(_ENUM_NS(EnumType)::_Base base) \
|
||||
{ return (EnumType)base; }
|
||||
{ return (EnumType)base; } \
|
||||
\
|
||||
} \
|
||||
}
|
||||
|
||||
#define ENUM(EnumType, Integral, ...) \
|
||||
_ENUM_DATA(EnumType, Integral, __VA_ARGS__); \
|
||||
|
||||
@ -1,4 +1,4 @@
|
||||
// Range properties and iteration over all constants.
|
||||
// Iteration over all constants.
|
||||
|
||||
#include <iostream>
|
||||
#include <enum.h>
|
||||
@ -7,17 +7,6 @@ ENUM(Channel, int, Red = 3, Green = 4, Blue = 0);
|
||||
|
||||
int main()
|
||||
{
|
||||
// Static range properties. Output is Red, Blue, Blue, Green, 3, 5.
|
||||
// See 6-traits.cc for an application of _first.
|
||||
std::cout << "first: " << (+Channel::_first).to_string() << std::endl;
|
||||
std::cout << "last: " << (+Channel::_last).to_string() << std::endl;
|
||||
std::cout << "minimum: " << (+Channel::_min).to_string() << std::endl;
|
||||
std::cout << "maximum: " << (+Channel::_max).to_string() << std::endl;
|
||||
std::cout << "count: " << Channel::_size << std::endl;
|
||||
std::cout << "span: " << Channel::_span << std::endl;
|
||||
|
||||
|
||||
|
||||
// Listing declared values. Output is 3 4 0.
|
||||
for (Channel channel : Channel::_values)
|
||||
std::cout << channel.to_integral() << " ";
|
||||
|
||||
@ -35,10 +35,6 @@ constexpr Channel channel_5 = *(Channel::_values.begin() + 1);
|
||||
constexpr const char *name_through_iterator = *(Channel::_names.begin() + 1);
|
||||
constexpr const char *name_through_subscript = Channel::_names[2];
|
||||
|
||||
// Range properties.
|
||||
constexpr Channel channel_6 = Channel::_max;
|
||||
constexpr size_t span = Channel::_span;
|
||||
|
||||
// Type name.
|
||||
constexpr auto name = Channel::_name;
|
||||
|
||||
@ -85,14 +81,12 @@ int main()
|
||||
print_validity(false, should_be_invalid_3);
|
||||
|
||||
PRINT(5);
|
||||
PRINT(6);
|
||||
|
||||
std::cout << "constexpr trimmed name: " << channel_1_name << std::endl;
|
||||
std::cout << "constexpr name through iterator: "
|
||||
<< name_through_iterator << std::endl;
|
||||
std::cout << "constexpr name through suscript: "
|
||||
<< name_through_subscript << std::endl;
|
||||
std::cout << "span: " << span << std::endl;
|
||||
std::cout << "type name: " << name << std::endl;
|
||||
|
||||
return 0;
|
||||
|
||||
@ -13,7 +13,7 @@
|
||||
template <typename Enum>
|
||||
constexpr const Enum default_()
|
||||
{
|
||||
return Enum::_first;
|
||||
return Enum::_values[0];
|
||||
}
|
||||
|
||||
// Make it possible to override the convention for specific enums.
|
||||
|
||||
@ -4,11 +4,22 @@
|
||||
#include <iostream>
|
||||
#include <enum.h>
|
||||
|
||||
// Computes the maximum value of an enum at compile time.
|
||||
template <typename Enum>
|
||||
constexpr Enum maximum(Enum accumulator = Enum::_values[0], size_t index = 1)
|
||||
{
|
||||
return
|
||||
index >= Enum::_size ? accumulator :
|
||||
Enum::_values[index] > accumulator ?
|
||||
maximum(+Enum::_values[index], index + 1) :
|
||||
maximum(accumulator, index + 1);
|
||||
}
|
||||
|
||||
ENUM(Channel, int, Red, Green, Blue);
|
||||
|
||||
int main()
|
||||
{
|
||||
using ChannelSet = std::bitset<Channel::_span>;
|
||||
using ChannelSet = std::bitset<maximum<Channel>() + 1>;
|
||||
|
||||
ChannelSet red_only;
|
||||
red_only.set(Channel::Red);
|
||||
|
||||
@ -54,7 +54,7 @@ void format_declaration(char *storage)
|
||||
std::strcat(storage, *name_iterator);
|
||||
std::strcat(storage, ", ");
|
||||
}
|
||||
std::strcat(storage, (+Enum::_last).to_string());
|
||||
std::strcat(storage, Enum::_names[Enum::_size - 1]);
|
||||
|
||||
std::strcat(storage, ");");
|
||||
|
||||
|
||||
@ -66,25 +66,6 @@ static_assert_1((std::is_convertible<Channel, Channel::_Integral>()));
|
||||
|
||||
|
||||
|
||||
// Range properties.
|
||||
static_assert_1(Channel::_size == 3);
|
||||
static_assert_1(Depth::_size == 2);
|
||||
|
||||
static_assert_1(Channel::_span == 3);
|
||||
static_assert_1(Depth::_span == 21);
|
||||
|
||||
static_assert_1(Channel::_first == Channel::Red);
|
||||
static_assert_1(Channel::_last == Channel::Blue);
|
||||
static_assert_1(Depth::_first == Depth::HighColor);
|
||||
static_assert_1(Depth::_last == Depth::TrueColor);
|
||||
|
||||
static_assert_1(Channel::_min == Channel::Red);
|
||||
static_assert_1(Channel::_max == Channel::Blue);
|
||||
static_assert_1(Depth::_min == Depth::TrueColor);
|
||||
static_assert_1(Depth::_max == Depth::HighColor);
|
||||
|
||||
|
||||
|
||||
// Constant values.
|
||||
static_assert_1((+Channel::Red).to_integral() == 0);
|
||||
static_assert_1((+Channel::Green).to_integral() == 1);
|
||||
@ -126,15 +107,18 @@ static_assert_1(!Channel::_is_valid_nocase("greeen"));
|
||||
|
||||
|
||||
// Iterables.
|
||||
static_assert_1(Channel::_size == 3);
|
||||
static_assert_1(Depth::_size == 2);
|
||||
static_assert_1(Channel::_values.size() == Channel::_size);
|
||||
static_assert_1(*Channel::_values.begin() == Channel::_first);
|
||||
static_assert_1(*Channel::_values.begin() == Channel::Red);
|
||||
static_assert_1(*(Channel::_values.begin() + 1) == Channel::Green);
|
||||
static_assert_1(*(Channel::_values.begin() + 2) == Channel::Blue);
|
||||
static_assert_1(Channel::_values[1] == Channel::Green);
|
||||
static_assert_1(Channel::_values[2] == Channel::Blue);
|
||||
|
||||
static_assert_1(Channel::_names.size() == Channel::_size);
|
||||
// The next one is a little janky, but actually the pointers should be the same.
|
||||
static_assert_1(*Channel::_names.begin() == (+Channel::_first).to_string());
|
||||
static_assert_1(*Channel::_names.begin() == (+Channel::Red).to_string());
|
||||
|
||||
|
||||
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user