Used explicit inline functions to simplify type hierarchy, also simplified iterables names.

This commit is contained in:
Anton Bachin 2015-05-23 21:00:36 -05:00
parent d0e4d9ffaa
commit 156b9d9b04
10 changed files with 238 additions and 236 deletions

383
enum.h
View File

@ -153,7 +153,7 @@
#define _ENUM_EAT_ASSIGN_SINGLE(EnumType, index, expression) \
((_enum::_eat_assign<EnumType>)Base::expression),
((_enum::_eat_assign<EnumType>)EnumType::expression),
#define _ENUM_EAT_ASSIGN(EnumType, ...) \
_ENUM_PP_MAP(_ENUM_EAT_ASSIGN_SINGLE, EnumType, __VA_ARGS__)
@ -393,206 +393,222 @@ inline void _trim_names(const char * const *raw_names,
#define _ENUM_TYPE(SetUnderlyingType, DisableDefault, SwitchType, \
GenerateSwitchType, ShortIterableDeclarations, \
ShortIterableAliases, GenerateStrings, DefineInitialize, \
CallInitialize, \
GenerateSwitchType, GenerateStrings, DeclareInitialize, \
DefineInitialize, CallInitialize, \
Enum, Integral, ...) \
\
namespace _enum { \
namespace _data_ ## Enum { \
\
struct Base { \
enum _enumerated SetUnderlyingType(Integral) { __VA_ARGS__ }; \
\
_ENUM_CONSTEXPR Base(_enumerated value) : _value(value) { } \
\
Integral _value; \
}; \
\
enum PutNamesInThisScopeAlso { __VA_ARGS__ }; \
\
_ENUM_CONSTEXPR const Base value_array[] = \
{ _ENUM_EAT_ASSIGN(Base, __VA_ARGS__) }; \
\
_ENUM_CONSTEXPR const size_t size = sizeof(value_array) / sizeof(Base); \
\
GenerateSwitchType(Integral, __VA_ARGS__); \
\
GenerateStrings(__VA_ARGS__) \
\
ShortIterableDeclarations \
\
} \
} \
\
class Enum : public _ENUM_NS(Enum)::Base { \
class Enum { \
protected: \
typedef better_enums::optional<Enum> _optional; \
typedef better_enums::optional<size_t> _optional_index; \
\
public: \
enum _enumerated SetUnderlyingType(Integral) { __VA_ARGS__ }; \
typedef Integral _integral; \
\
_ENUM_CONSTEXPR Enum(_enumerated value) : Base(value) { } \
_ENUM_CONSTEXPR Enum(_ENUM_NS(Enum)::Base value) : Base(value) { } \
\
_ENUM_CONSTEXPR _integral _to_integral() const \
{ \
return _value; \
} \
\
_ENUM_CONSTEXPR static const _optional \
_from_integral_nothrow(_integral value) \
{ \
return \
_enum::_map_index<Enum>(_ENUM_NS(Enum)::value_array, \
_from_int_loop(value)); \
} \
\
_ENUM_CONSTEXPR static const Enum _from_integral(_integral value) \
{ \
return \
_enum::_or_throw(_from_integral_nothrow(value), \
"Enum::_from_integral: invalid argument"); \
} \
\
_ENUM_CONSTEXPR static const Enum _from_integral_unchecked(_integral value)\
{ \
return (_enumerated)value; \
} \
\
_ENUM_CONSTEXPR const char* _to_string() const \
{ \
return \
_enum::_or_throw( \
_enum::_map_index<const char*>( \
_ENUM_NS(Enum)::name_array(), \
_from_int_loop(CallInitialize(_value))), \
"Enum::to_string: invalid enum value"); \
} \
\
_ENUM_CONSTEXPR static const _optional \
_from_string_nothrow(const char *name) \
{ \
return \
_enum::_map_index<Enum>( \
_ENUM_NS(Enum)::value_array, _from_string_loop(name)); \
} \
\
_ENUM_CONSTEXPR static const Enum _from_string(const char *name) \
{ \
return \
_enum::_or_throw(_from_string_nothrow(name), \
"Enum::_from_string: invalid argument"); \
} \
\
_ENUM_CONSTEXPR static const _optional \
_from_string_nocase_nothrow(const char *name) \
{ \
return \
_enum::_map_index<Enum>(_ENUM_NS(Enum)::value_array, \
_from_string_nocase_loop(name)); \
} \
\
_ENUM_CONSTEXPR static const Enum _from_string_nocase(const char *name) \
{ \
return \
_enum::_or_throw(_from_string_nocase_nothrow(name), \
"Enum::_from_string_nocase: invalid argument"); \
} \
\
_ENUM_CONSTEXPR static bool _is_valid(_integral value) \
{ \
return _from_int_loop(value); \
} \
\
_ENUM_CONSTEXPR static bool _is_valid(const char *name) \
{ \
return _from_string_loop(name); \
} \
\
_ENUM_CONSTEXPR static bool _is_valid_nocase(const char *name) \
{ \
return _from_string_nocase_loop(name); \
} \
_ENUM_CONSTEXPR Enum(_enumerated value) : _value(value) { } \
\
_ENUM_CONSTEXPR operator SwitchType(Enum)() const \
{ \
return (SwitchType(Enum))_value; \
} \
\
typedef _enum::_Iterable<_ENUM_NS(Enum)::Base> _value_iterable; \
typedef _enum::_Iterable<const char*> _name_iterable; \
_ENUM_CONSTEXPR _integral _to_integral() const; \
_ENUM_CONSTEXPR static Enum _from_integral(_integral value); \
_ENUM_CONSTEXPR static Enum _from_integral_unchecked(_integral value); \
_ENUM_CONSTEXPR static _optional _from_integral_nothrow(_integral value); \
\
typedef _value_iterable::iterator _value_iterator; \
typedef _name_iterable::iterator _name_iterator; \
_ENUM_CONSTEXPR const char* _to_string() const; \
_ENUM_CONSTEXPR static Enum _from_string(const char *name); \
_ENUM_CONSTEXPR static _optional _from_string_nothrow(const char *name); \
\
_ENUM_CONSTEXPR static const size_t _size = _ENUM_NS(Enum)::size; \
_ENUM_CONSTEXPR static Enum _from_string_nocase(const char *name); \
_ENUM_CONSTEXPR static _optional \
_from_string_nocase_nothrow(const char *name); \
\
_ENUM_CONSTEXPR static const char* _name_() \
{ \
return #Enum; \
} \
_ENUM_CONSTEXPR static bool _is_valid(_integral value); \
_ENUM_CONSTEXPR static bool _is_valid(const char *name); \
_ENUM_CONSTEXPR static bool _is_valid_nocase(const char *name); \
\
_ENUM_CONSTEXPR static _value_iterable _values_() \
{ \
return _value_iterable(_ENUM_NS(Enum)::value_array, _size); \
} \
typedef _enum::_Iterable<Enum> _value_iterable; \
typedef _enum::_Iterable<const char*> _name_iterable; \
\
_ENUM_CONSTEXPR static _name_iterable _names_() \
{ \
return \
_name_iterable(_ENUM_NS(Enum)::name_array(), \
CallInitialize(_size)); \
} \
typedef _value_iterable::iterator _value_iterator; \
typedef _name_iterable::iterator _name_iterator; \
\
ShortIterableAliases(Enum) \
_ENUM_CONSTEXPR static const size_t _size = _ENUM_PP_COUNT(__VA_ARGS__); \
\
_ENUM_CONSTEXPR static const char* _name(); \
_ENUM_CONSTEXPR static _value_iterable _values(); \
_ENUM_CONSTEXPR static _name_iterable _names(); \
\
_integral _value; \
\
DisableDefault(Enum) \
\
protected: \
DefineInitialize(Enum) \
DeclareInitialize \
\
_ENUM_CONSTEXPR static _optional_index \
_from_int_loop(_integral value, size_t index = 0) \
{ \
return \
index == _size ? _optional_index() : \
_ENUM_NS(Enum)::value_array[index]._value == value ? \
_optional_index(index) : \
_from_int_loop(value, index + 1); \
} \
\
_from_int_loop(_integral value, size_t index = 0); \
_ENUM_CONSTEXPR static _optional_index \
_from_string_loop(const char *name, size_t index = 0) \
{ \
return \
index == _size ? _optional_index() : \
_enum::_namesMatch(_ENUM_NS(Enum)::name_array()[index], name) ? \
_optional_index(index) : \
_from_string_loop(name, index + 1); \
} \
\
_from_string_loop(const char *name, size_t index = 0); \
_ENUM_CONSTEXPR static _optional_index \
_from_string_nocase_loop(const char *name, size_t index = 0) \
{ \
return \
index == _size ? _optional_index() : \
_enum::_namesMatchNocase( \
_ENUM_NS(Enum)::name_array()[index], name) ? \
_optional_index(index) : \
_from_string_nocase_loop(name, index + 1); \
} \
_from_string_nocase_loop(const char *name, size_t index = 0); \
}; \
\
_ENUM_CONSTEXPR inline const Enum operator +(Enum::_enumerated enumerated) \
{ return (Enum)enumerated; } \
\
namespace _enum { \
namespace _data_ ## Enum { \
\
_ENUM_CONSTEXPR inline const Enum operator +(_ENUM_NS(Enum)::Base base) \
{ return (Enum)base; } \
enum PutNamesInThisScopeAlso { __VA_ARGS__ }; \
\
_ENUM_CONSTEXPR const Enum value_array[] = \
{ _ENUM_EAT_ASSIGN(Enum, __VA_ARGS__) }; \
\
GenerateStrings(Enum, __VA_ARGS__) \
\
} \
} \
\
_ENUM_CONSTEXPR inline const Enum operator +(Enum::_enumerated enumerated) \
{ return (Enum)enumerated; } \
\
_ENUM_CONSTEXPR inline Enum::_integral Enum::_to_integral() const \
{ \
return _value; \
} \
\
_ENUM_CONSTEXPR inline Enum \
Enum::_from_integral_unchecked(Enum::_integral value) \
{ \
return (_enumerated)value; \
} \
\
_ENUM_CONSTEXPR inline Enum Enum::_from_integral(Enum::_integral value) \
{ \
return \
_enum::_or_throw(_from_integral_nothrow(value), \
"Enum::_from_integral: invalid argument"); \
} \
\
_ENUM_CONSTEXPR inline Enum::_optional \
Enum::_from_integral_nothrow(Enum::_integral value) \
{ \
return \
_enum::_map_index<Enum>(_ENUM_NS(Enum)::value_array, \
_from_int_loop(value)); \
} \
\
_ENUM_CONSTEXPR inline const char* Enum::_to_string() const \
{ \
return \
_enum::_or_throw( \
_enum::_map_index<const char*>( \
_ENUM_NS(Enum)::name_array(), \
_from_int_loop(CallInitialize(_value))), \
"Enum::to_string: invalid enum value"); \
} \
\
_ENUM_CONSTEXPR inline Enum Enum::_from_string(const char *name) \
{ \
return \
_enum::_or_throw(_from_string_nothrow(name), \
"Enum::_from_string: invalid argument"); \
} \
\
_ENUM_CONSTEXPR inline Enum::_optional \
Enum::_from_string_nothrow(const char *name) \
{ \
return \
_enum::_map_index<Enum>( \
_ENUM_NS(Enum)::value_array, _from_string_loop(name)); \
} \
\
_ENUM_CONSTEXPR inline Enum Enum::_from_string_nocase(const char *name) \
{ \
return \
_enum::_or_throw(_from_string_nocase_nothrow(name), \
"Enum::_from_string_nocase: invalid argument"); \
} \
\
_ENUM_CONSTEXPR inline Enum::_optional \
Enum::_from_string_nocase_nothrow(const char *name) \
{ \
return \
_enum::_map_index<Enum>(_ENUM_NS(Enum)::value_array, \
_from_string_nocase_loop(name)); \
} \
\
_ENUM_CONSTEXPR inline bool Enum::_is_valid(Enum::_integral value) \
{ \
return _from_int_loop(value); \
} \
\
_ENUM_CONSTEXPR inline bool Enum::_is_valid(const char *name) \
{ \
return _from_string_loop(name); \
} \
\
_ENUM_CONSTEXPR inline bool Enum::_is_valid_nocase(const char *name) \
{ \
return _from_string_nocase_loop(name); \
} \
\
_ENUM_CONSTEXPR inline const char* Enum::_name() \
{ \
return #Enum; \
} \
\
_ENUM_CONSTEXPR inline Enum::_value_iterable Enum::_values() \
{ \
return _value_iterable(_ENUM_NS(Enum)::value_array, _size); \
} \
\
_ENUM_CONSTEXPR inline Enum::_name_iterable Enum::_names() \
{ \
return _name_iterable(_ENUM_NS(Enum)::name_array(), CallInitialize(_size));\
} \
\
DefineInitialize(Enum) \
\
_ENUM_CONSTEXPR inline Enum::_optional_index \
Enum::_from_int_loop(Enum::_integral value, size_t index) \
{ \
return \
index == _size ? _optional_index() : \
_ENUM_NS(Enum)::value_array[index]._value == value ? \
_optional_index(index) : \
_from_int_loop(value, index + 1); \
} \
\
_ENUM_CONSTEXPR inline Enum::_optional_index \
Enum::_from_string_loop(const char *name, size_t index) \
{ \
return \
index == _size ? _optional_index() : \
_enum::_namesMatch(_ENUM_NS(Enum)::name_array()[index], name) ? \
_optional_index(index) : \
_from_string_loop(name, index + 1); \
} \
\
_ENUM_CONSTEXPR inline Enum::_optional_index \
Enum::_from_string_nocase_loop(const char *name, size_t index) \
{ \
return \
index == _size ? _optional_index() : \
_enum::_namesMatchNocase( \
_ENUM_NS(Enum)::name_array()[index], name) ? \
_optional_index(index) : \
_from_string_nocase_loop(name, index + 1); \
} \
\
_ENUM_CONSTEXPR inline bool operator ==(const Enum &a, const Enum &b) \
{ return a._value == b._value; } \
@ -605,10 +621,7 @@ _ENUM_CONSTEXPR inline bool operator <=(const Enum &a, const Enum &b) \
_ENUM_CONSTEXPR inline bool operator >(const Enum &a, const Enum &b) \
{ return a._value > b._value; } \
_ENUM_CONSTEXPR inline bool operator >=(const Enum &a, const Enum &b) \
{ return a._value >= b._value; } \
\
} \
}
{ return a._value >= b._value; }
@ -621,7 +634,7 @@ _ENUM_CONSTEXPR inline bool operator >=(const Enum &a, const Enum &b) \
// C++98, C++11
#define _ENUM_DISABLE_DEFAULT_BY_PRIVATE(Type) \
private: Type() : Base((_enumerated)0) { }
private: Type() { }
// C++11
#define _ENUM_DISABLE_DEFAULT_BY_DELETE(Type) \
@ -642,25 +655,8 @@ _ENUM_CONSTEXPR inline bool operator >=(const Enum &a, const Enum &b) \
#define _ENUM_GENERATE_SWITCH_TYPE_ENUM_CLASS(Integral, ...) \
enum class EnumClassForSwitchStatements : Integral { __VA_ARGS__ }
// C++98, C++11
#define _ENUM_SHORT_ITERABLE_DECLARATIONS_NOT_AVAILABLE
// C++11
#define _ENUM_SHORT_ITERABLE_DECLARATIONS \
constexpr const _Iterable<Base> values{value_array, size}; \
constexpr const _Iterable<const char*> names{name_array(), size};
// C++98, C++11
#define _ENUM_SHORT_ITERABLE_ALIASES_NOT_AVAILABLE(Enum)
// C++11
#define _ENUM_SHORT_ITERABLE_ALIASES(Enum) \
constexpr static const _value_iterable &_values = _ENUM_NS(Enum)::values; \
constexpr static const _name_iterable &_names = _ENUM_NS(Enum)::names; \
constexpr static const char *_name = #Enum;
// C++98
#define _ENUM_GENERATE_STRINGS_PREPARE_FOR_RUNTIME_WRAPPED(...) \
#define _ENUM_GENERATE_STRINGS_PREPARE_FOR_RUNTIME_WRAPPED(Enum, ...) \
inline const char** raw_names() \
{ \
static const char* value[] = { _ENUM_STRINGIZE(__VA_ARGS__) }; \
@ -669,7 +665,7 @@ _ENUM_CONSTEXPR inline bool operator >=(const Enum &a, const Enum &b) \
\
inline const char** name_array() \
{ \
static const char* value[size]; \
static const char* value[Enum::_size]; \
return value; \
} \
\
@ -680,13 +676,13 @@ _ENUM_CONSTEXPR inline bool operator >=(const Enum &a, const Enum &b) \
}
// C++11 fast version
#define _ENUM_GENERATE_STRINGS_PREPARE_FOR_RUNTIME_CONSTEXPR(...) \
#define _ENUM_GENERATE_STRINGS_PREPARE_FOR_RUNTIME_CONSTEXPR(Enum, ...) \
constexpr const char *raw_names[] = { _ENUM_STRINGIZE(__VA_ARGS__) }; \
const char *name_array[size]; \
const char *name_array[Enum::_size]; \
bool initialized = false;
// C++11 slow all-constexpr version
#define _ENUM_GENERATE_STRINGS_COMPILE_TIME(...) \
#define _ENUM_GENERATE_STRINGS_COMPILE_TIME(Enum, ...) \
_ENUM_TRIM_STRINGS(__VA_ARGS__) \
constexpr const char * const the_name_array[] = \
{ _ENUM_REFER_TO_STRINGS(__VA_ARGS__) }; \
@ -695,9 +691,16 @@ _ENUM_CONSTEXPR inline bool operator >=(const Enum &a, const Enum &b) \
return the_name_array; \
}
// C++98, C++11 fast version
#define _ENUM_DECLARE_INITIALIZE \
static int initialize();
// C++11 slow all-constexpr version
#define _ENUM_INITIALIZE_DECLARATION_NOT_NEEDED
// C++98, C++11 fast version
#define _ENUM_DEFINE_INITIALIZE(Enum) \
static int initialize() \
inline int Enum::initialize() \
{ \
if (_ENUM_NS(Enum)::initialized()) \
return 0; \
@ -730,9 +733,8 @@ _ENUM_CONSTEXPR inline bool operator >=(const Enum &a, const Enum &b) \
_ENUM_DISABLE_DEFAULT_BY_DELETE, \
_ENUM_SWITCH_TYPE_IS_ENUM_CLASS, \
_ENUM_GENERATE_SWITCH_TYPE_ENUM_CLASS, \
_ENUM_SHORT_ITERABLE_DECLARATIONS, \
_ENUM_SHORT_ITERABLE_ALIASES, \
_ENUM_GENERATE_STRINGS_COMPILE_TIME, \
_ENUM_INITIALIZE_DECLARATION_NOT_NEEDED, \
_ENUM_DEFINE_INITIALIZE_NOT_NEEDED, \
_ENUM_CALL_INITIALIZE_IS_NO_OP, \
Enum, Integral, __VA_ARGS__)
@ -744,9 +746,8 @@ _ENUM_CONSTEXPR inline bool operator >=(const Enum &a, const Enum &b) \
_ENUM_DISABLE_DEFAULT_BY_PRIVATE, \
_ENUM_SWITCH_TYPE_IS_REGULAR_ENUM, \
_ENUM_GENERATE_SWITCH_TYPE_REGULAR_ENUM, \
_ENUM_SHORT_ITERABLE_DECLARATIONS_NOT_AVAILABLE, \
_ENUM_SHORT_ITERABLE_ALIASES_NOT_AVAILABLE, \
_ENUM_GENERATE_STRINGS_PREPARE_FOR_RUNTIME_WRAPPED, \
_ENUM_DECLARE_INITIALIZE, \
_ENUM_DEFINE_INITIALIZE, \
_ENUM_CALL_INITIALIZE, \
Enum, Integral, __VA_ARGS__)

View File

@ -93,7 +93,7 @@ int main()
// The type name is available as a string.
std::cout << Channel::_name << std::endl;
std::cout << Channel::_name() << std::endl;

View File

@ -8,12 +8,12 @@ ENUM(Channel, int, Red = 3, Green = 4, Blue = 0)
int main()
{
// 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 << std::endl;
// Listing declared names. Output is Red Green Blue.
for (const char *name : Channel::_names)
for (const char *name : Channel::_names())
std::cout << name << " ";
std::cout << std::endl;
@ -22,7 +22,7 @@ int main()
// Direct iterator usage. Output is Red.
std::cout
<< "first (using iterator): "
<< *Channel::_names.begin()
<< *Channel::_names().begin()
<< std::endl;
return 0;

View File

@ -31,12 +31,13 @@ constexpr bool should_be_valid_3 = Channel::_is_valid_nocase("red");
constexpr bool should_be_invalid_3 = Channel::_is_valid_nocase("reed");
// _names and _values collections and iterators.
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];
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];
// Type name.
constexpr auto name = Channel::_name;
constexpr auto name = Channel::_name();
// Explicit promotion.
constexpr int converted = (+Channel::Green)._to_integral();

View File

@ -30,7 +30,7 @@ int main()
std::map<const char*, Channel> map = {{"first", Channel::Blue}};
map.insert({"second", Channel::Green});
for (Channel channel : Channel::_values)
for (Channel channel : Channel::_values())
map.insert({channel._to_string(), channel});
bool first = true;

View File

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

View File

@ -6,12 +6,12 @@
// 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)
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) :
Enum::_values()[index] > accumulator ?
maximum(Enum::_values()[index], index + 1) :
maximum(accumulator, index + 1);
}
@ -29,7 +29,7 @@ int main()
ChannelSet red_and_blue = red_only | blue_only;
for (Channel channel : Channel::_values) {
for (Channel channel : Channel::_values()) {
std::cout
<< channel._to_string()
<< " bit is set to "

View File

@ -24,7 +24,7 @@ constexpr size_t total_names_length(size_t accumulator = 0, size_t index = 0)
return
index == Enum::_size ? accumulator :
total_names_length<Enum>
(accumulator + string_length(Enum::_names[index]), index + 1);
(accumulator + string_length(Enum::_names()[index]), index + 1);
}
// Computes the total length of an ENUM declaration, assuming the type is int.
@ -36,7 +36,7 @@ template <typename Enum>
constexpr size_t declaration_length()
{
return
4 + 1 + string_length(Enum::_name) + 1 + 1 + 3 + 1 + 1 +
4 + 1 + string_length(Enum::_name()) + 1 + 1 + 3 + 1 + 1 +
total_names_length<Enum>() + (Enum::_size - 1) * 2 + 1 + 1 + 1;
}
@ -45,16 +45,16 @@ template <typename Enum>
void format_declaration(char *storage)
{
std::strcat(storage, "ENUM(");
std::strcat(storage, Enum::_name);
std::strcat(storage, Enum::_name());
std::strcat(storage, ", int, ");
for (auto name_iterator = Enum::_names.begin();
name_iterator < Enum::_names.end() - 1; ++name_iterator) {
for (auto name_iterator = Enum::_names().begin();
name_iterator < Enum::_names().end() - 1; ++name_iterator) {
std::strcat(storage, *name_iterator);
std::strcat(storage, ", ");
}
std::strcat(storage, Enum::_names[Enum::_size - 1]);
std::strcat(storage, Enum::_names()[Enum::_size - 1]);
std::strcat(storage, ");");

View File

@ -15,9 +15,9 @@ ENUM(Compression, short, None, Huffman, Default = Huffman)
// Type properties.
static_assert_1(std::is_class<Channel>());
static_assert_1(!std::is_trivial<Channel>());
static_assert_1(std::is_trivial<Channel>());
static_assert_1(std::is_standard_layout<Channel>());
static_assert_1(!std::is_pod<Channel>());
static_assert_1(std::is_pod<Channel>());
static_assert_1(std::is_literal_type<Channel>());
@ -69,7 +69,7 @@ static_assert_1(!(std::is_convertible<Channel, Depth>()));
static_assert_1(!(std::is_convertible<Channel, Channel::_enumerated>()));
static_assert_1(!(std::is_convertible<decltype(+Channel::Red),
Channel::_integral>()));
static_assert_1(!(std::is_convertible<decltype(Channel::_values[0]),
static_assert_1(!(std::is_convertible<decltype(Channel::_values()[0]),
Channel::_integral>()));
@ -117,16 +117,16 @@ 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::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::_values().size() == Channel::_size);
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);
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::Red)._to_string());
static_assert_1(*Channel::_names().begin() == (+Channel::Red)._to_string());
@ -156,44 +156,44 @@ class EnumTests : public CxxTest::TestSuite {
void test_value_iterable()
{
auto value_iterator = Channel::_values.begin();
auto value_iterator = Channel::_values().begin();
TS_ASSERT_EQUALS(*value_iterator, Channel::Red);
TS_ASSERT_DIFFERS(value_iterator, Channel::_values.end());
TS_ASSERT_DIFFERS(value_iterator, Channel::_values().end());
++value_iterator;
TS_ASSERT_EQUALS(*value_iterator, Channel::Green);
TS_ASSERT_DIFFERS(value_iterator, Channel::_values.end());
TS_ASSERT_DIFFERS(value_iterator, Channel::_values().end());
++value_iterator;
TS_ASSERT_EQUALS(*value_iterator, Channel::Blue);
TS_ASSERT_DIFFERS(value_iterator, Channel::_values.end());
TS_ASSERT_DIFFERS(value_iterator, Channel::_values().end());
++value_iterator;
TS_ASSERT_EQUALS(value_iterator, Channel::_values.end());
TS_ASSERT_EQUALS(value_iterator, Channel::_values().end());
}
void test_name_iterable()
{
auto name_iterator = Channel::_names.begin();
auto name_iterator = Channel::_names().begin();
TS_ASSERT_EQUALS(strcmp(*name_iterator, "Red"), 0);
TS_ASSERT_DIFFERS(name_iterator, Channel::_names.end());
TS_ASSERT_DIFFERS(name_iterator, Channel::_names().end());
++name_iterator;
TS_ASSERT_EQUALS(strcmp(*name_iterator, "Green"), 0);
TS_ASSERT_DIFFERS(name_iterator, Channel::_names.end());
TS_ASSERT_DIFFERS(name_iterator, Channel::_names().end());
++name_iterator;
TS_ASSERT_EQUALS(strcmp(*name_iterator, "Blue"), 0);
TS_ASSERT_DIFFERS(name_iterator, Channel::_names.end());
TS_ASSERT_DIFFERS(name_iterator, Channel::_names().end());
++name_iterator;
TS_ASSERT_EQUALS(name_iterator, Channel::_names.end());
TS_ASSERT_EQUALS(name_iterator, Channel::_names().end());
}
void test_type_name()
{
TS_ASSERT_EQUALS(strcmp(Channel::_name, "Channel"), 0);
TS_ASSERT_EQUALS(strcmp(Depth::_name, "Depth"), 0);
TS_ASSERT_EQUALS(strcmp(Compression::_name, "Compression"), 0);
TS_ASSERT_EQUALS(strcmp(Channel::_name(), "Channel"), 0);
TS_ASSERT_EQUALS(strcmp(Depth::_name(), "Depth"), 0);
TS_ASSERT_EQUALS(strcmp(Compression::_name(), "Compression"), 0);
}
};

View File

@ -3,5 +3,5 @@
void print(Channel channel)
{
std::cout << Channel::_name << "::" << channel._to_string() << std::endl;
std::cout << Channel::_name() << "::" << channel._to_string() << std::endl;
}