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:
Anton Bachin 2015-05-18 09:26:38 -05:00
parent 1cfe53e827
commit d9bd109172
7 changed files with 27 additions and 91 deletions

56
enum.h
View File

@ -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 } // namespace _enum
@ -571,11 +535,6 @@ constexpr const size_t _size = \
\ \
static_assert(_size > 0, "no constants defined in enum type"); \ 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__); \ _ENUM_TRIM_STRINGS(__VA_ARGS__); \
\ \
constexpr const char * const _name_array[] = \ 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 char *_name = #EnumType; \
constexpr static const size_t _size = _ENUM_NS(EnumType)::_size; \ 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; \ EnumType() = delete; \
constexpr EnumType(_Enumerated value) : _Base(value) { } \ constexpr EnumType(_Enumerated value) : _Base(value) { } \
constexpr EnumType(_ENUM_NS(EnumType)::_Base 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) \ constexpr const EnumType operator +(EnumType::_Enumerated enumerated) \
{ return (EnumType)enumerated; } \ { return (EnumType)enumerated; } \
\ \
namespace _enum { \
namespace _data_ ## EnumType { \
\
constexpr const EnumType operator +(_ENUM_NS(EnumType)::_Base base) \ constexpr const EnumType operator +(_ENUM_NS(EnumType)::_Base base) \
{ return (EnumType)base; } { return (EnumType)base; } \
\
} \
}
#define ENUM(EnumType, Integral, ...) \ #define ENUM(EnumType, Integral, ...) \
_ENUM_DATA(EnumType, Integral, __VA_ARGS__); \ _ENUM_DATA(EnumType, Integral, __VA_ARGS__); \

View File

@ -1,4 +1,4 @@
// Range properties and iteration over all constants. // Iteration over all constants.
#include <iostream> #include <iostream>
#include <enum.h> #include <enum.h>
@ -7,17 +7,6 @@ ENUM(Channel, int, Red = 3, Green = 4, Blue = 0);
int main() 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. // Listing declared values. Output is 3 4 0.
for (Channel channel : Channel::_values) for (Channel channel : Channel::_values)
std::cout << channel.to_integral() << " "; std::cout << channel.to_integral() << " ";

View File

@ -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_iterator = *(Channel::_names.begin() + 1);
constexpr const char *name_through_subscript = Channel::_names[2]; 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. // Type name.
constexpr auto name = Channel::_name; constexpr auto name = Channel::_name;
@ -85,14 +81,12 @@ int main()
print_validity(false, should_be_invalid_3); print_validity(false, should_be_invalid_3);
PRINT(5); PRINT(5);
PRINT(6);
std::cout << "constexpr trimmed name: " << channel_1_name << std::endl; std::cout << "constexpr trimmed name: " << channel_1_name << std::endl;
std::cout << "constexpr name through iterator: " std::cout << "constexpr name through iterator: "
<< name_through_iterator << std::endl; << name_through_iterator << std::endl;
std::cout << "constexpr name through suscript: " std::cout << "constexpr name through suscript: "
<< name_through_subscript << std::endl; << name_through_subscript << std::endl;
std::cout << "span: " << span << std::endl;
std::cout << "type name: " << name << std::endl; std::cout << "type name: " << name << std::endl;
return 0; return 0;

View File

@ -13,7 +13,7 @@
template <typename Enum> template <typename Enum>
constexpr const Enum default_() constexpr const Enum default_()
{ {
return Enum::_first; return Enum::_values[0];
} }
// Make it possible to override the convention for specific enums. // Make it possible to override the convention for specific enums.

View File

@ -4,11 +4,22 @@
#include <iostream> #include <iostream>
#include <enum.h> #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); ENUM(Channel, int, Red, Green, Blue);
int main() int main()
{ {
using ChannelSet = std::bitset<Channel::_span>; using ChannelSet = std::bitset<maximum<Channel>() + 1>;
ChannelSet red_only; ChannelSet red_only;
red_only.set(Channel::Red); red_only.set(Channel::Red);

View File

@ -54,7 +54,7 @@ void format_declaration(char *storage)
std::strcat(storage, *name_iterator); std::strcat(storage, *name_iterator);
std::strcat(storage, ", "); std::strcat(storage, ", ");
} }
std::strcat(storage, (+Enum::_last).to_string()); std::strcat(storage, Enum::_names[Enum::_size - 1]);
std::strcat(storage, ");"); std::strcat(storage, ");");

View File

@ -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. // Constant values.
static_assert_1((+Channel::Red).to_integral() == 0); static_assert_1((+Channel::Red).to_integral() == 0);
static_assert_1((+Channel::Green).to_integral() == 1); static_assert_1((+Channel::Green).to_integral() == 1);
@ -126,15 +107,18 @@ static_assert_1(!Channel::_is_valid_nocase("greeen"));
// Iterables. // 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.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() + 1) == Channel::Green);
static_assert_1(*(Channel::_values.begin() + 2) == Channel::Blue); static_assert_1(*(Channel::_values.begin() + 2) == Channel::Blue);
static_assert_1(Channel::_values[1] == Channel::Green); static_assert_1(Channel::_values[1] == Channel::Green);
static_assert_1(Channel::_values[2] == Channel::Blue); static_assert_1(Channel::_values[2] == Channel::Blue);
static_assert_1(Channel::_names.size() == Channel::_size); static_assert_1(Channel::_names.size() == Channel::_size);
// The next one is a little janky, but actually the pointers should be the same. // 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());