types/description: add underlying_comparator for enum descriptions

This commit is contained in:
Danny Robson 2019-08-30 15:30:45 +10:00
parent fd64ca6bce
commit 3866249607
2 changed files with 53 additions and 1 deletions

View File

@ -5,7 +5,7 @@
///////////////////////////////////////////////////////////////////////////////
enum an_enum_type { AN_ENUM_VALUE };
enum an_enum_type : i16 { AN_ENUM_VALUE };
//-----------------------------------------------------------------------------
@ -55,6 +55,19 @@ int main ()
"enums are described as such"
);
{
auto const a = cruft::types::make_description<an_enum_type> ();
auto const b = cruft::types::make_description<std::underlying_type_t<an_enum_type>> ();
tap.expect_neq (a, b, "enum and underlying_type_t raw equality");
cruft::types::underlying_comparator const cmp {};
tap.expect (cmp (a, b), "enum and underlying_type equality");
auto const c = cruft::types::make_description<u32> ();
static_assert (!std::is_same_v<u32, std::underlying_type_t<an_enum_type>>);
tap.expect (!cmp (a, c), "enum and underlying_type inequality");
}
auto const enum_type_descriptor = cruft::types::make_description<an_enum_type> ();
tap.expect (

View File

@ -132,6 +132,45 @@ namespace cruft::types {
}
/// A comparator that compares values as equal if they are an enum and the
/// underlying_type of said enum.
///
/// This is distinct from the raw equality operator so as to not pessimise
/// the usability of the equality operator (for tasks that required strict
/// equality).
struct underlying_comparator {
bool operator() (
description const &a,
description const &b
) const noexcept {
// If one of the descriptions is ENUM then both need to be either ENUM
// or INTEGER (because we try to compare enums and their underlying
// types as equal).
if (a.category == category::ENUM || b.category == category::ENUM) {
if (a.category != category::ENUM && a.category != category::INTEGER)
return false;
if (b.category != category::ENUM && b.category != category::INTEGER)
return false;
// Indices only need to match if they're both an ENUM,
// otherwise we're testing the underlying type.
if (a.category == category::ENUM && b.category == category::ENUM)
if (a.index != b.index)
return false;
} else {
if (a.index != b.index)
return false;
}
// All details other must be identical;
return a.signedness == b.signedness &&
a.width == b.width &&
a.arity == b.arity &&
a.alignment == b.alignment;
};
};
//-------------------------------------------------------------------------
template <typename T, typename = void>
struct category_traits;