Removed most weak symbols. Iterators should now be random access.

The remaining weak symbol will be removed when string conversions become
constexpr. Iterator are random access because they are now pointers.
This commit is contained in:
Anton Bachin 2015-05-17 18:47:51 -05:00
parent 460bb806a3
commit 1465901bc1
2 changed files with 258 additions and 360 deletions

2
.gitignore vendored
View File

@ -2,4 +2,4 @@
*.exe
scratch/
doc-publish/
test/*.cc
test/cxxtest/*.cc

616
enum.h
View File

@ -334,96 +334,41 @@ namespace _enum {
#define _ENUM_WEAK __attribute__((weak))
template <typename Element>
struct _Iterable {
using iterator = const Element*;
constexpr iterator begin() const { return iterator(_array); }
constexpr iterator end() const { return iterator(_array + _size); }
constexpr size_t size() const { return _size; }
constexpr _Iterable(const Element *array, size_t size) :
_array(array), _size(size) { };
template <typename EnumType, typename Iterator>
class _Iterable;
template <typename Derived>
class _BaseIterator {
public:
Derived& operator ++()
{ ++_index; return static_cast<Derived&>(*this); }
constexpr bool operator ==(const Derived &other) const
{ return other._index == _index; }
constexpr bool operator !=(const Derived &other) const
{ return other._index != _index; }
protected:
constexpr _BaseIterator(size_t index) : _index(index) { }
size_t _index;
private:
const Element * const _array;
const size_t _size;
};
template <typename EnumType>
class _ValueIterator :
public _BaseIterator<_ValueIterator<EnumType>> {
using _Super = _BaseIterator<_ValueIterator<EnumType>>;
public:
constexpr EnumType operator *() const
{ return EnumType::_value_array[_Super::_index]; }
private:
using _Super::_Super;
friend _Iterable<EnumType, _ValueIterator<EnumType>>;
};
template <typename EnumType>
class _NameIterator :
public _BaseIterator<_NameIterator<EnumType>> {
using _Super = _BaseIterator<_NameIterator<EnumType>>;
public:
const char* operator *() const
{ return EnumType::_getProcessedName(_Super::_index); }
private:
using _Super::_Super;
friend _Iterable<EnumType, _NameIterator<EnumType>>;
};
template <typename EnumType, typename Iterator>
class _Iterable {
public:
using iterator = Iterator;
constexpr iterator begin() const { return iterator(0); }
constexpr iterator end() const { return iterator(EnumType::_size); }
constexpr size_t size() const { return EnumType::_size; }
private:
constexpr _Iterable() { };
friend EnumType;
};
template <typename UnderlyingType>
class _eat_assign {
private:
UnderlyingType _value;
public:
explicit constexpr _eat_assign(UnderlyingType value) : _value(value) { }
struct _eat_assign {
explicit constexpr _eat_assign(EnumType value) : _value(value) { }
template <typename Any>
constexpr UnderlyingType operator =(Any dummy) const
constexpr EnumType operator =(Any dummy) const
{ return _value; }
constexpr operator UnderlyingType () const { return _value; }
constexpr operator EnumType () const { return _value; }
private:
EnumType _value;
};
#define _ENUM_EAT_ASSIGN_SINGLE(UnderlyingType, expression) \
((_enum::_eat_assign<UnderlyingType>)expression)
#define _ENUM_EAT_ASSIGN_SINGLE(EnumType, expression) \
((_enum::_eat_assign<EnumType>)_Base::expression)
#define _ENUM_EAT_ASSIGN(UnderlyingType, ...) \
_ENUM_PP_MAP(_ENUM_EAT_ASSIGN_SINGLE, UnderlyingType, __VA_ARGS__)
#define _ENUM_EAT_ASSIGN(EnumType, ...) \
_ENUM_PP_MAP(_ENUM_EAT_ASSIGN_SINGLE, EnumType, __VA_ARGS__)
@ -490,39 +435,36 @@ constexpr bool _namesMatchNocase(const char *stringizedName,
template <typename UnderlyingType>
constexpr UnderlyingType _findMinLoop(const UnderlyingType *values,
size_t valueCount, size_t index,
UnderlyingType best)
template <typename EnumType>
constexpr EnumType _findMinLoop(const EnumType *values, size_t valueCount,
size_t index, EnumType best)
{
return
index == valueCount ? best :
values[index] < best ?
values[index]._value < best._value ?
_findMinLoop(values, valueCount, index + 1, values[index]) :
_findMinLoop(values, valueCount, index + 1, best);
}
template <typename UnderlyingType>
constexpr UnderlyingType _findMin(const UnderlyingType *values,
size_t valueCount)
template <typename EnumType>
constexpr EnumType _findMin(const EnumType *values, size_t valueCount)
{
return _findMinLoop(values, valueCount, 1, values[0]);
}
template <typename UnderlyingType>
constexpr UnderlyingType _findMaxLoop(const UnderlyingType *values,
size_t valueCount, size_t index,
UnderlyingType best)
template <typename EnumType>
constexpr EnumType _findMaxLoop(const EnumType *values, size_t valueCount,
size_t index, EnumType best)
{
return
index == valueCount ? best :
values[index] > best ?
values[index]._value > best._value ?
_findMaxLoop(values, valueCount, index + 1, values[index]) :
_findMaxLoop(values, valueCount, index + 1, best);
}
template <typename UnderlyingType>
constexpr UnderlyingType _findMax(const UnderlyingType *values, size_t count)
template <typename EnumType>
constexpr EnumType _findMax(const EnumType *values, size_t count)
{
return _findMaxLoop(values, count, 1, values[0]);
}
@ -573,274 +515,230 @@ static inline const char * const* _processNames(const char * const *rawNames,
return processedNames;
}
#define _ENUM_TAG(EnumType) _tag_ ## EnumType
#define _ENUM_TAG_DECLARATION(EnumType) \
namespace _enum { \
struct _ENUM_TAG(EnumType); \
}
template <typename Tag> class _GeneratedArrays;
#define _ENUM_ARRAYS(EnumType, Integral, Tag, ...) \
namespace _enum { \
\
template <> \
class _GeneratedArrays<Tag> { \
protected: \
using _Integral = Integral; \
\
public: \
constexpr static const char* _name = #EnumType; \
\
enum _Enumerated : _Integral { __VA_ARGS__ }; \
\
protected: \
constexpr static _Enumerated _value_array[] = \
{ _ENUM_EAT_ASSIGN(_Enumerated, __VA_ARGS__) }; \
\
constexpr static const char *_name_array[] = \
{ _ENUM_STRINGIZE(__VA_ARGS__) }; \
}; \
\
}
#define _ENUM_NOT_FOUND ((size_t)-1)
template <typename Tag>
class _Enum : public _GeneratedArrays<Tag> {
protected:
using _arrays = _GeneratedArrays<Tag>;
using _arrays::_value_array;
using _arrays::_name_array;
public:
using typename _arrays::_Enumerated;
using typename _arrays::_Integral;
constexpr static const size_t _size =
sizeof(_value_array) / sizeof(_Enumerated);
static_assert(_size > 0, "no constants defined in enum type");
constexpr static const _Enumerated _first = _value_array[0];
constexpr static const _Enumerated _last = _value_array[_size - 1];
constexpr static const _Enumerated _min = _findMin(_value_array, _size);
constexpr static const _Enumerated _max = _findMax(_value_array, _size);
constexpr static const _Integral _span = _max - _min + 1;
_Enum() = delete;
constexpr _Enum(_Enumerated constant) : _value(constant) { }
constexpr _Integral to_integral() const
{
return _value;
}
constexpr static const _Enum _from_integral(_Integral value)
{
return _value_array[_from_int_loop(value, true)];
}
constexpr static const _Enum _from_integral_unchecked(_Integral value)
{
return (_Enumerated)value;
}
const char* to_string() const
{
_processNames();
for (size_t index = 0; index < _size; ++index) {
if (_value_array[index] == _value)
return _processedNames[index];
}
throw std::domain_error("Enum::_to_string: invalid enum value");
}
constexpr static const _Enum _from_string(const char *name)
{
return _value_array[_from_string_loop(name, true)];
}
constexpr static const _Enum _from_string_nocase(const char *name)
{
return _value_array[_from_string_nocase_loop(name, true)];
}
constexpr static bool _is_valid(_Integral value)
{
return _from_int_loop(value, false) != _ENUM_NOT_FOUND;
}
constexpr static bool _is_valid(const char *name)
{
return _from_string_loop(name, false) != _ENUM_NOT_FOUND;
}
constexpr static bool _is_valid_nocase(const char *name)
{
return _from_string_nocase_loop(name, false) != _ENUM_NOT_FOUND;
}
constexpr operator _Enumerated() const { return _value; }
protected:
_Enumerated _value;
static const char * const *_processedNames;
static void _processNames()
{
if (_processedNames == nullptr)
_processedNames = _enum::_processNames(_name_array, _size);
}
static const char* _getProcessedName(size_t index)
{
_processNames();
return _processedNames[index];
}
using _ValueIterable = _Iterable<_Enum, _ValueIterator<_Enum>>;
using _NameIterable = _Iterable<_Enum, _NameIterator<_Enum>>;
friend _ValueIterator<_Enum>;
friend _NameIterator<_Enum>;
public:
static const _ValueIterable _values;
static const _NameIterable _names;
protected:
constexpr static size_t _from_int_loop(_Integral value,
bool throw_exception,
size_t index = 0)
{
return
index == _size ?
(throw_exception ?
throw std::runtime_error(
"Enum::_from_integral: invalid integer value") :
_ENUM_NOT_FOUND) :
_value_array[index] == value ? index :
_from_int_loop(value, throw_exception, index + 1);
}
constexpr static size_t _from_string_loop(const char *name,
bool throw_exception,
size_t index = 0)
{
return
index == _size ?
(throw_exception ?
throw std::runtime_error(
"Enum::_from_string: invalid string argument") :
_ENUM_NOT_FOUND) :
_namesMatch(_name_array[index], name) ? index :
_from_string_loop(name, throw_exception, index + 1);
}
constexpr static size_t _from_string_nocase_loop(const char *name,
bool throw_exception,
size_t index = 0)
{
return
index == _size ?
(throw_exception ?
throw std::runtime_error(
"Enum::_from_string_nocase: invalid string argument") :
_ENUM_NOT_FOUND) :
_namesMatchNocase(_name_array[index], name) ? index :
_from_string_nocase_loop(name, throw_exception, index + 1);
}
public:
constexpr bool operator ==(const _Enum &other) const
{ return _value == other._value; }
constexpr bool operator ==(const _Enumerated value) const
{ return _value == value; }
template <typename T> bool operator ==(T other) const = delete;
constexpr bool operator !=(const _Enum &other) const
{ return !(*this == other); }
constexpr bool operator !=(const _Enumerated value) const
{ return !(*this == value); }
template <typename T> bool operator !=(T other) const = delete;
constexpr bool operator <(const _Enum &other) const
{ return _value < other._value; }
constexpr bool operator <(const _Enumerated value) const
{ return _value < value; }
template <typename T> bool operator <(T other) const = delete;
constexpr bool operator <=(const _Enum &other) const
{ return _value <= other._value; }
constexpr bool operator <=(const _Enumerated value) const
{ return _value <= value; }
template <typename T> bool operator <=(T other) const = delete;
constexpr bool operator >(const _Enum &other) const
{ return _value > other._value; }
constexpr bool operator >(const _Enumerated value) const
{ return _value > value; }
template <typename T> bool operator >(T other) const = delete;
constexpr bool operator >=(const _Enum &other) const
{ return _value >= other._value; }
constexpr bool operator >=(const _Enumerated value) const
{ return _value >= value; }
template <typename T> bool operator >=(T other) const = delete;
int operator -() const = delete;
template <typename T> int operator +(T other) const = delete;
template <typename T> int operator -(T other) const = delete;
template <typename T> int operator *(T other) const = delete;
template <typename T> int operator /(T other) const = delete;
template <typename T> int operator %(T other) const = delete;
template <typename T> int operator <<(T other) const = delete;
template <typename T> int operator >>(T other) const = delete;
int operator ~() const = delete;
template <typename T> int operator &(T other) const = delete;
template <typename T> int operator |(T other) const = delete;
template <typename T> int operator ^(T other) const = delete;
int operator !() const = delete;
template <typename T> int operator &&(T other) const = delete;
template <typename T> int operator ||(T other) const = delete;
};
#define _ENUM_GLOBALS(EnumType, Tag) \
namespace _enum { \
\
constexpr const EnumType operator +(EnumType::_Enumerated enumerated) \
{ return (EnumType)enumerated; } \
\
template <> \
constexpr EnumType::_ValueIterable _ENUM_WEAK EnumType::_values{}; \
\
template <> \
constexpr EnumType::_NameIterable _ENUM_WEAK EnumType::_names{}; \
\
constexpr _GeneratedArrays<Tag>::_Enumerated _ENUM_WEAK \
_GeneratedArrays<Tag>::_value_array[]; \
\
constexpr const char * _ENUM_WEAK _GeneratedArrays<Tag>::_name_array[]; \
\
template <> \
const char * const * _ENUM_WEAK EnumType::_processedNames = nullptr; \
\
}
} // namespace _enum
#define _ENUM_DATA(EnumType, Integral, ...) \
namespace _enum { \
namespace _data_ ## EnumType { \
\
struct _Base { \
enum _Enumerated : Integral { __VA_ARGS__ }; \
\
_Base() = delete; \
constexpr _Base(_Enumerated value) : _value(value) { } \
\
constexpr bool operator ==(const _Base &other) const \
{ return _value == other._value; } \
constexpr bool operator ==(_Enumerated value) const \
{ return _value == value; } \
constexpr bool operator !=(const _Base &other) const \
{ return !(*this == other); } \
constexpr bool operator !=(_Enumerated value) const \
{ return !(*this == value); } \
constexpr bool operator <(const _Base &other) const \
{ return _value < other._value; } \
constexpr bool operator <(_Enumerated value) const \
{ return _value < value; } \
constexpr bool operator <=(const _Base &other) const \
{ return _value <= other._value; } \
constexpr bool operator <=(_Enumerated value) const \
{ return _value <= value; } \
constexpr bool operator >(const _Base &other) const \
{ return _value > other._value; } \
constexpr bool operator >(_Enumerated value) const \
{ return _value > value; } \
constexpr bool operator >=(const _Base &other) const \
{ return _value >= other._value; } \
constexpr bool operator >=(_Enumerated value) const \
{ return _value >= value; } \
\
_Enumerated _value; \
}; \
\
enum { __VA_ARGS__ }; \
\
constexpr const _Base _value_array[] = \
{ _ENUM_EAT_ASSIGN(_Base, __VA_ARGS__) }; \
\
constexpr const char * const _name_array[] = \
{ _ENUM_STRINGIZE(__VA_ARGS__) }; \
\
constexpr const size_t _size = \
sizeof(_value_array) / sizeof(_Base::_Enumerated); \
\
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); \
\
constexpr const _Iterable<_Base> _values{_value_array, _size}; \
constexpr const _Iterable<const char*> _names{_name_array, _size}; \
\
} \
}
#define _ENUM_NS(EnumType) _enum::_data_ ## EnumType
#define _ENUM_NOT_FOUND ((size_t)-1)
#define _ENUM_TYPE(EnumType, Integral, ...) \
class EnumType : public _ENUM_NS(EnumType)::_Base { \
protected: \
constexpr static auto _value_array = _ENUM_NS(EnumType)::_value_array; \
constexpr static auto _name_array = _ENUM_NS(EnumType)::_name_array; \
\
public: \
using _Integral = Integral; \
\
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) { } \
\
constexpr _Integral to_integral() const \
{ \
return _value; \
} \
\
constexpr static const EnumType _from_integral(_Integral value) \
{ \
return _value_array[_from_int_loop(value, true)]; \
} \
\
constexpr static const EnumType _from_integral_unchecked(_Integral value) \
{ \
return (_Enumerated)value; \
} \
\
const char* to_string() const \
{ \
_processNames(); \
\
for (size_t index = 0; index < _size; ++index) { \
if (_value_array[index]._value == _value) \
return _processedNames[index]; \
} \
\
throw std::domain_error("Enum::_to_string: invalid enum value"); \
} \
\
constexpr static const EnumType _from_string(const char *name) \
{ \
return _value_array[_from_string_loop(name, true)]; \
} \
\
constexpr static const EnumType _from_string_nocase(const char *name) \
{ \
return _value_array[_from_string_nocase_loop(name, true)]; \
} \
\
constexpr static bool _is_valid(_Integral value) \
{ \
return _from_int_loop(value, false) != _ENUM_NOT_FOUND; \
} \
\
constexpr static bool _is_valid(const char *name) \
{ \
return _from_string_loop(name, false) != _ENUM_NOT_FOUND; \
} \
\
constexpr static bool _is_valid_nocase(const char *name) \
{ \
return _from_string_nocase_loop(name, false) != _ENUM_NOT_FOUND; \
} \
\
constexpr operator _Enumerated() const { return _value; } \
\
protected: \
static const char * const *_processedNames; \
\
static void _processNames() \
{ \
if (_processedNames == nullptr) \
_processedNames = _enum::_processNames(_name_array, _size); \
} \
\
static const char* _getProcessedName(size_t index) \
{ \
_processNames(); \
return _processedNames[index]; \
} \
\
public: \
constexpr static auto &_values = _ENUM_NS(EnumType)::_values; \
constexpr static auto &_names = _ENUM_NS(EnumType)::_names; \
\
protected: \
constexpr static size_t _from_int_loop(_Integral value, \
bool throw_exception, \
size_t index = 0) \
{ \
return \
index == _size ? \
(throw_exception ? \
throw std::runtime_error( \
"Enum::_from_integral: invalid integer value") : \
_ENUM_NOT_FOUND) : \
_value_array[index]._value == value ? index : \
_from_int_loop(value, throw_exception, index + 1); \
} \
\
constexpr static size_t _from_string_loop(const char *name, \
bool throw_exception, \
size_t index = 0) \
{ \
return \
index == _size ? \
(throw_exception ? \
throw std::runtime_error( \
"Enum::_from_string: invalid string argument") : \
_ENUM_NOT_FOUND) : \
_enum::_namesMatch(_name_array[index], name) ? index : \
_from_string_loop(name, throw_exception, index + 1); \
} \
\
constexpr static size_t _from_string_nocase_loop(const char *name, \
bool throw_exception, \
size_t index = 0) \
{ \
return \
index == _size ? \
(throw_exception ? \
throw std::runtime_error( \
"Enum::_from_string_nocase: invalid string argument") :\
_ENUM_NOT_FOUND) : \
_enum::_namesMatchNocase(_name_array[index], name) ? index : \
_from_string_nocase_loop(name, throw_exception, index + 1); \
} \
};
#define _ENUM_WEAK __attribute__((weak))
#define _ENUM_GLOBALS(EnumType) \
constexpr const EnumType operator +(EnumType::_Enumerated enumerated) \
{ return (EnumType)enumerated; } \
\
constexpr const EnumType operator +(_ENUM_NS(EnumType)::_Base base) \
{ return (EnumType)base; } \
\
const char * const * _ENUM_WEAK EnumType::_processedNames = nullptr;
#define ENUM(EnumType, Integral, ...) \
_ENUM_TAG_DECLARATION(EnumType); \
_ENUM_ARRAYS(EnumType, Integral, _ENUM_TAG(EnumType), __VA_ARGS__); \
using EnumType = _enum::_Enum<_enum::_ENUM_TAG(EnumType)>; \
_ENUM_GLOBALS(EnumType, _ENUM_TAG(EnumType));
_ENUM_DATA(EnumType, Integral, __VA_ARGS__); \
_ENUM_TYPE(EnumType, Integral, __VA_ARGS__); \
_ENUM_GLOBALS(EnumType);