From 38662496077f006cfadcfd3a9c8e445a82024c0e Mon Sep 17 00:00:00 2001 From: Danny Robson Date: Fri, 30 Aug 2019 15:30:45 +1000 Subject: [PATCH] types/description: add underlying_comparator for enum descriptions --- test/types/description.cpp | 15 ++++++++++++++- types/description.hpp | 39 ++++++++++++++++++++++++++++++++++++++ 2 files changed, 53 insertions(+), 1 deletion(-) diff --git a/test/types/description.cpp b/test/types/description.cpp index 6b684f79..b7c5ecfa 100644 --- a/test/types/description.cpp +++ b/test/types/description.cpp @@ -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 (); + auto const b = cruft::types::make_description> (); + + 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 (); + static_assert (!std::is_same_v>); + tap.expect (!cmp (a, c), "enum and underlying_type inequality"); + } auto const enum_type_descriptor = cruft::types::make_description (); tap.expect ( diff --git a/types/description.hpp b/types/description.hpp index 361c7fcd..fba1aa27 100644 --- a/types/description.hpp +++ b/types/description.hpp @@ -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 struct category_traits;