BLI: provide a default hash for enums

This avoids some boilerplate code that was necessary when using enums
as keys in maps or sets.
This commit is contained in:
Jacques Lucke 2021-03-17 11:37:46 +01:00
parent e00a47ffd6
commit ac60e64745
3 changed files with 30 additions and 11 deletions

View File

@ -49,16 +49,6 @@ enum class GeometryOwnershipType {
ReadOnly = 2,
};
/* Make it possible to use the component type as key in hash tables. */
namespace blender {
template<> struct DefaultHash<GeometryComponentType> {
uint64_t operator()(const GeometryComponentType &value) const
{
return (uint64_t)value;
}
};
} // namespace blender
namespace blender::bke {
class ComponentAttributeProviders;
}

View File

@ -88,11 +88,18 @@ namespace blender {
* If there is no other specialization of #DefaultHash for a given type, try to call `hash()` on
* the value. If there is no such method, this will result in a compiler error. Usually that means
* that you have to implement a hash function using one of three strategies listed above.
*
* In the case of an enum type, the default hash is just to cast the enum value to an integer.
*/
template<typename T> struct DefaultHash {
uint64_t operator()(const T &value) const
{
return value.hash();
if constexpr (std::is_enum_v<T>) {
return (uint64_t)value;
}
else {
return value.hash();
}
}
};

View File

@ -565,6 +565,28 @@ TEST(map, AddOrModifyExceptions)
EXPECT_ANY_THROW({ map.add_or_modify(3, create_fn, modify_fn); });
}
namespace {
enum class TestEnum {
A = 0,
B = 1,
C = 2,
D = 1,
};
}
TEST(map, EnumKey)
{
Map<TestEnum, int> map;
map.add(TestEnum::A, 4);
map.add(TestEnum::B, 6);
EXPECT_EQ(map.lookup(TestEnum::A), 4);
EXPECT_EQ(map.lookup(TestEnum::B), 6);
EXPECT_EQ(map.lookup(TestEnum::D), 6);
EXPECT_FALSE(map.contains(TestEnum::C));
map.lookup(TestEnum::D) = 10;
EXPECT_EQ(map.lookup(TestEnum::B), 10);
}
/**
* Set this to 1 to activate the benchmark. It is disabled by default, because it prints a lot.
*/