From d9bd10917201b6e2276319a50b2de02a19f0878c Mon Sep 17 00:00:00 2001 From: Anton Bachin Date: Mon, 18 May 2015 09:26:38 -0500 Subject: [PATCH] Removed range properties. They can now be easily computed using the random access iterators. There appears to be a slight performance improvement. --- enum.h | 56 +++++----------------------------- example/2-iterate.cc | 13 +------- example/4-constexpr.cc | 6 ---- example/6-traits.cc | 2 +- example/7-bitset.cc | 13 +++++++- example/8-constexpr-iterate.cc | 2 +- test/cxxtest/tests.h | 26 +++------------- 7 files changed, 27 insertions(+), 91 deletions(-) diff --git a/enum.h b/enum.h index 0d8cf0b..443a2d3 100644 --- a/enum.h +++ b/enum.h @@ -447,42 +447,6 @@ constexpr bool _namesMatchNocase(const char *stringizedName, -template -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 -constexpr EnumType _findMin(const EnumType *values, size_t valueCount) -{ - return _findMinLoop(values, valueCount, 1, values[0]); -} - -template -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 -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__); \ diff --git a/example/2-iterate.cc b/example/2-iterate.cc index 6f33bd4..63ce547 100644 --- a/example/2-iterate.cc +++ b/example/2-iterate.cc @@ -1,4 +1,4 @@ -// Range properties and iteration over all constants. +// Iteration over all constants. #include #include @@ -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() << " "; diff --git a/example/4-constexpr.cc b/example/4-constexpr.cc index 22cc5bb..d2ad456 100644 --- a/example/4-constexpr.cc +++ b/example/4-constexpr.cc @@ -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; diff --git a/example/6-traits.cc b/example/6-traits.cc index 657f851..f050f14 100644 --- a/example/6-traits.cc +++ b/example/6-traits.cc @@ -13,7 +13,7 @@ template constexpr const Enum default_() { - return Enum::_first; + return Enum::_values[0]; } // Make it possible to override the convention for specific enums. diff --git a/example/7-bitset.cc b/example/7-bitset.cc index 69100f2..e643466 100644 --- a/example/7-bitset.cc +++ b/example/7-bitset.cc @@ -4,11 +4,22 @@ #include #include +// Computes the maximum value of an enum at compile time. +template +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; + using ChannelSet = std::bitset() + 1>; ChannelSet red_only; red_only.set(Channel::Red); diff --git a/example/8-constexpr-iterate.cc b/example/8-constexpr-iterate.cc index c48a5e3..756ca9a 100644 --- a/example/8-constexpr-iterate.cc +++ b/example/8-constexpr-iterate.cc @@ -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, ");"); diff --git a/test/cxxtest/tests.h b/test/cxxtest/tests.h index 17a0041..d691d35 100644 --- a/test/cxxtest/tests.h +++ b/test/cxxtest/tests.h @@ -66,25 +66,6 @@ static_assert_1((std::is_convertible())); -// 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());