types/description: add underlying_comparator for enum descriptions
This commit is contained in:
parent
fd64ca6bce
commit
3866249607
@ -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"
|
"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> ();
|
auto const enum_type_descriptor = cruft::types::make_description<an_enum_type> ();
|
||||||
tap.expect (
|
tap.expect (
|
||||||
|
@ -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>
|
template <typename T, typename = void>
|
||||||
struct category_traits;
|
struct category_traits;
|
||||||
|
Loading…
Reference in New Issue
Block a user