From 5a677ac72bbc44d8ac2f60beafe680adb14bd4a6 Mon Sep 17 00:00:00 2001 From: Sven Scharmentke Date: Tue, 16 Jul 2019 11:36:16 +0200 Subject: [PATCH] Support using better-enum as key in dictionaries and maps (#77) This enabled hashing so that unordered_map are supported. --- enum.h | 11 +++++++++ test/cxxtest/general.h | 55 +++++++++++++++++++++++++++++------------- 2 files changed, 49 insertions(+), 17 deletions(-) diff --git a/enum.h b/enum.h index 3ba66b3..83c5122 100644 --- a/enum.h +++ b/enum.h @@ -1283,4 +1283,15 @@ BETTER_ENUMS_CONSTEXPR_ map make_map(T (*f)(Enum)) } +#define BETTER_ENUMS_DECLARE_STD_HASH(type) \ + namespace std { \ + template <> struct hash \ + { \ + size_t operator()(const type &x) const \ + { \ + return std::hash()(x._to_integral()); \ + } \ + }; \ + } + #endif // #ifndef BETTER_ENUMS_ENUM_H diff --git a/test/cxxtest/general.h b/test/cxxtest/general.h index 7dbef05..014fcec 100644 --- a/test/cxxtest/general.h +++ b/test/cxxtest/general.h @@ -31,7 +31,10 @@ BETTER_ENUM(Namespaced, short, One, Two) // be changed to be more precise in the future. #ifdef BETTER_ENUMS_HAVE_CONSTEXPR_ +BETTER_ENUMS_DECLARE_STD_HASH(Channel) + #include +#include // Type properties. static_assert_1(std::is_class()); @@ -161,6 +164,24 @@ static_assert_1(same_string(Depth::_names()[0], "HighColor")); // Run-time testing. +class HashTests : public CxxTest::TestSuite { + public: + void test_same_values() + { +#ifdef _ENUM_HAVE_CONSTEXPR + TS_ASSERT_EQUALS( + std::hash().operator()(Channel::Red), + std::hash().operator()(0)); + TS_ASSERT_EQUALS( + std::hash().operator()(Channel::Green), + std::hash().operator()(1)); + TS_ASSERT_EQUALS( + std::hash().operator()(Channel::Blue), + std::hash().operator()(2)); +#endif // #ifdef _ENUM_HAVE_CONSTEXPR + } +}; + class EnumTests : public CxxTest::TestSuite { public: void test_constant_values() @@ -313,59 +334,59 @@ class EnumTests : public CxxTest::TestSuite { +test::Namespaced::One); TS_ASSERT_EQUALS(strcmp(*test::Namespaced::_names().begin(), "One"), 0); } - + void test_to_index() { TS_ASSERT_EQUALS((+Channel::Red)._to_index(), 0); TS_ASSERT_EQUALS((+Channel::Green)._to_index(), 1); TS_ASSERT_EQUALS((+Channel::Blue)._to_index(), 2); - + TS_ASSERT_EQUALS((+Depth::HighColor)._to_index(), 0); TS_ASSERT_EQUALS((+Depth::TrueColor)._to_index(), 1); - + TS_ASSERT_EQUALS((+Compression::None)._to_index(), 0); TS_ASSERT_EQUALS((+Compression::Huffman)._to_index(), 1); // TS_ASSERT_EQUALS((+Compression::Default)._to_index(), 2); // This won't pass as Compression::Huffman == Compression::Default } - + void test_from_index() { TS_ASSERT_EQUALS((+Channel::Red), Channel::_from_index(0)); TS_ASSERT_EQUALS((+Channel::Green), Channel::_from_index(1)); TS_ASSERT_EQUALS((+Channel::Blue), Channel::_from_index(2)); TS_ASSERT_THROWS(Channel::_from_index(42), std::runtime_error); - + TS_ASSERT_EQUALS((+Depth::HighColor), Depth::_from_index(0)); TS_ASSERT_EQUALS((+Depth::TrueColor), Depth::_from_index(1)); TS_ASSERT_THROWS(Depth::_from_index(42), std::runtime_error); - + TS_ASSERT_EQUALS((+Compression::None), Compression::_from_index(0)); TS_ASSERT_EQUALS((+Compression::Huffman), Compression::_from_index(1)); TS_ASSERT_EQUALS((+Compression::Default), Compression::_from_index(2)); TS_ASSERT_THROWS(Compression::_from_index(42), std::runtime_error); } - + void test_from_index_nothrow() { better_enums::optional maybe_channel = Channel::_from_index_nothrow(0); TS_ASSERT(maybe_channel); TS_ASSERT_EQUALS(*maybe_channel, +Channel::Red); - + maybe_channel = Channel::_from_index_nothrow(1); TS_ASSERT(maybe_channel); TS_ASSERT_EQUALS(*maybe_channel, +Channel::Green); - + maybe_channel = Channel::_from_index_nothrow(2); TS_ASSERT(maybe_channel); TS_ASSERT_EQUALS(*maybe_channel, +Channel::Blue); maybe_channel = Channel::_from_index_nothrow(45); TS_ASSERT(!maybe_channel); - + better_enums::optional maybe_depth = Depth::_from_index_nothrow(0); TS_ASSERT(maybe_depth); TS_ASSERT_EQUALS(*maybe_depth, +Depth::HighColor); - + maybe_depth = Depth::_from_index_nothrow(1); TS_ASSERT(maybe_depth); TS_ASSERT_EQUALS(*maybe_depth, +Depth::TrueColor); @@ -376,11 +397,11 @@ class EnumTests : public CxxTest::TestSuite { better_enums::optional maybe_compression = Compression::_from_index_nothrow(0); TS_ASSERT(maybe_compression); TS_ASSERT_EQUALS(*maybe_compression, +Compression::None); - + maybe_compression = Compression::_from_index_nothrow(1); TS_ASSERT(maybe_compression); TS_ASSERT_EQUALS(*maybe_compression, +Compression::Huffman); - + maybe_compression = Compression::_from_index_nothrow(2); TS_ASSERT(maybe_compression); TS_ASSERT_EQUALS(*maybe_compression, +Compression::Default); @@ -388,17 +409,17 @@ class EnumTests : public CxxTest::TestSuite { maybe_compression = Compression::_from_index_nothrow(45); TS_ASSERT(!maybe_compression); } - + void test_from_index_unchecked() { - + TS_ASSERT_EQUALS((+Channel::Red), Channel::_from_index_unchecked(0)); TS_ASSERT_EQUALS((+Channel::Green), Channel::_from_index_unchecked(1)); TS_ASSERT_EQUALS((+Channel::Blue), Channel::_from_index_unchecked(2)); - + TS_ASSERT_EQUALS((+Depth::HighColor), Depth::_from_index_unchecked(0)); TS_ASSERT_EQUALS((+Depth::TrueColor), Depth::_from_index_unchecked(1)); - + TS_ASSERT_EQUALS((+Compression::None), Compression::_from_index_unchecked(0)); TS_ASSERT_EQUALS((+Compression::Huffman), Compression::_from_index_unchecked(1)); TS_ASSERT_EQUALS((+Compression::Default), Compression::_from_index_unchecked(2));