any/meta_any: revert changes to introduce ::hash

This commit is contained in:
Michele Caini
2022-02-22 12:15:09 +01:00
parent 07a36123e5
commit 507bafdd9c
7 changed files with 0 additions and 177 deletions

View File

@@ -7,7 +7,6 @@
* [Introduction](#introduction)
* [Any as in any type](#any-as-in-any-type)
* [Hashing of any objects](#hashing-of-any-objects)
* [Small buffer optimization](#small-buffer-optimization)
* [Alignment requirement](#alignment-requirement)
* [Compressed pair](#compressed-pair)
@@ -168,29 +167,6 @@ The only difference is that, in the case of `EnTT`, these won't raise exceptions
but will only trigger an assert in debug mode, otherwise resulting in undefined
behavior in case of misuse in release mode.
## Hashing of any objects
As for the `any` class, the hashing topic deserves a section of its own.<br/>
It's indeed possible to extract the hash value (as in `std::hash`) of an object
managed by `any`:
```cpp
const std::size_t hash = any.hash();
```
However, there are some limitations:
* The instance of `any` **must** not be empty, otherwise the returned value is
that of `std::hash<const void *>{}(nullptr)`.
* The underlying object **must** support this operation, otherwise the returned
value is that of `std::hash<const void *>{}(nullptr)`.
Unfortunately, it's not possible to trigger a compile-time error in these cases.
This would prevent users from using non-hashable types with `any`.<br/>
A compromise has therefore been made that could change over time but which
appears to be acceptable today for the conceivable uses of this feature.
## Small buffer optimization
The `any` class uses a technique called _small buffer optimization_ to reduce

View File

@@ -2,7 +2,6 @@
#define ENTT_CORE_ANY_HPP
#include <cstddef>
#include <functional>
#include <memory>
#include <type_traits>
#include <utility>
@@ -28,7 +27,6 @@ class basic_any {
assign,
destroy,
compare,
hash,
get
};
@@ -96,12 +94,6 @@ class basic_any {
} else {
return (element == other) ? other : nullptr;
}
case operation::hash:
if constexpr(is_std_hashable_v<Type>) {
*static_cast<std::size_t *>(const_cast<void *>(other)) = std::hash<Type>{}(*element);
return element;
}
break;
case operation::get:
return element;
}
@@ -388,23 +380,6 @@ public:
return (mode == policy::owner);
}
/**
* @brief Returns the hash value of the contained object.
*
* If the underlying object isn't _hashable_, the hash of its address is
* returned once converted to `const void *`.
*
* @return The hash value of the contained object or its address if any,
* `std::hash<const void *>{}({})` otherwise.
*/
[[nodiscard]] std::size_t hash() const ENTT_NOEXCEPT {
if(std::size_t value{}; vtable && vtable(operation::hash, *this, &value)) {
return value;
}
return std::hash<const void *>{}(nullptr);
}
private:
union {
const void *instance;
@@ -512,21 +487,4 @@ basic_any<Len, Align> forward_as_any(Type &&value) {
} // namespace entt
namespace std {
/*! @brief `std::hash` specialization for `entt::any`. */
template<>
struct hash<entt::any> {
/**
* @brief Returns the hash value of the parameter.
* @param any The object to return the hash for.
* @return The hash value of the parameter.
*/
[[nodiscard]] std::size_t operator()(const entt::any &any) const ENTT_NOEXCEPT {
return any.hash();
}
};
} // namespace std
#endif

View File

@@ -2,7 +2,6 @@
#define ENTT_CORE_TYPE_TRAITS_HPP
#include <cstddef>
#include <functional>
#include <iterator>
#include <type_traits>
#include <utility>
@@ -592,30 +591,6 @@ struct is_equality_comparable<Type, std::void_t<decltype(std::declval<Type>() ==
template<typename Type>
inline constexpr bool is_equality_comparable_v = is_equality_comparable<Type>::value;
/**
* @brief Provides the member constant `value` to true if a given type is
* _hashable_, false otherwise.
* @tparam Type The type to test.
*/
template<typename Type, typename = void>
struct is_std_hashable: std::false_type {};
/*! @brief Specialization required to get around an issue with clang-cl. */
template<>
struct is_std_hashable<void>: std::false_type {};
/*! @copydoc is_std_hashable */
template<typename Type>
struct is_std_hashable<Type, std::enable_if_t<std::is_same_v<decltype(std::declval<const std::hash<Type> &>()(*std::declval<Type *>())), std::size_t>>>
: std::true_type {};
/**
* @brief Helper variable template.
* @tparam Type The type to test.
*/
template<typename Type>
inline constexpr auto is_std_hashable_v = is_std_hashable<Type>::value;
/**
* @brief Transcribes the constness of a type to another type.
* @tparam To The type to which to transcribe the constness.

View File

@@ -2,7 +2,6 @@
#define ENTT_META_META_HPP
#include <cstddef>
#include <functional>
#include <iterator>
#include <memory>
#include <type_traits>
@@ -564,11 +563,6 @@ public:
return storage.owner();
}
/*! @copydoc any::hash */
[[nodiscard]] std::size_t hash() const ENTT_NOEXCEPT {
return storage.hash();
}
private:
any storage;
internal::meta_type_node *node;
@@ -1844,21 +1838,4 @@ inline bool meta_associative_container::erase(meta_any key) {
} // namespace entt
namespace std {
/*! @brief `std::hash` specialization for `entt::meta_any`. */
template<>
struct hash<entt::meta_any> {
/**
* @brief Returns the hash value of the parameter.
* @param any The object to return the hash for.
* @return The hash value of the parameter.
*/
[[nodiscard]] std::size_t operator()(const entt::meta_any &any) const ENTT_NOEXCEPT {
return any.hash();
}
};
} // namespace std
#endif

View File

@@ -1171,33 +1171,6 @@ TEST_F(Any, CompareVoid) {
ASSERT_FALSE(entt::any{} != any);
}
TEST_F(Any, Hashable) {
const int value = 42;
entt::any any{value};
const entt::any ref{std::in_place_type<const int &>, value};
ASSERT_TRUE(any);
ASSERT_TRUE(ref);
ASSERT_EQ(any.hash(), std::hash<int>{}(value));
ASSERT_EQ(std::hash<int>{}(value), std::hash<entt::any>{}(ref));
ASSERT_EQ(ref.hash(), std::hash<entt::any>{}(any));
}
TEST_F(Any, NotHashable) {
const not_comparable value{};
entt::any any{value};
const entt::any ref{std::in_place_type<const not_comparable &>, value};
ASSERT_TRUE(any);
ASSERT_TRUE(ref);
ASSERT_EQ(any.hash(), std::hash<const void *>{}(nullptr));
ASSERT_EQ(std::hash<const void *>{}(nullptr), std::hash<entt::any>{}(ref));
ASSERT_EQ(ref.hash(), std::hash<entt::any>{}(any));
ASSERT_EQ(any.hash(), entt::any{}.hash());
}
TEST_F(Any, AnyCast) {
entt::any any{42};
const auto &cany = any;

View File

@@ -165,15 +165,6 @@ TEST(IsEqualityComparable, Functionalities) {
static_assert(!entt::is_equality_comparable_v<void>);
}
TEST(IsStdHashable, Functionalities) {
static_assert(entt::is_std_hashable_v<int>);
static_assert(entt::is_std_hashable_v<char>);
static_assert(entt::is_std_hashable_v<double>);
static_assert(!entt::is_std_hashable_v<nlohmann_json_like>);
static_assert(!entt::is_std_hashable_v<not_comparable>);
static_assert(!entt::is_std_hashable_v<void>);
}
TEST(ConstnessAs, Functionalities) {
static_assert(std::is_same_v<entt::constness_as_t<int, char>, int>);
static_assert(std::is_same_v<entt::constness_as_t<const int, char>, int>);

View File

@@ -1076,33 +1076,6 @@ TEST_F(MetaAny, CompareVoid) {
ASSERT_TRUE(entt::meta_any{} != any);
}
TEST_F(MetaAny, Hashable) {
const int value = 42;
entt::meta_any any{value};
const entt::meta_any ref{std::in_place_type<const int &>, value};
ASSERT_TRUE(any);
ASSERT_TRUE(ref);
ASSERT_EQ(any.hash(), std::hash<int>{}(value));
ASSERT_EQ(std::hash<int>{}(value), std::hash<entt::meta_any>{}(ref));
ASSERT_EQ(ref.hash(), std::hash<entt::meta_any>{}(any));
}
TEST_F(MetaAny, NotHashable) {
const not_comparable_t value{};
entt::meta_any any{value};
const entt::meta_any ref{std::in_place_type<const not_comparable_t &>, value};
ASSERT_TRUE(any);
ASSERT_TRUE(ref);
ASSERT_EQ(any.hash(), std::hash<const void *>{}(nullptr));
ASSERT_EQ(std::hash<const void *>{}(nullptr), std::hash<entt::any>{}(ref));
ASSERT_EQ(ref.hash(), std::hash<entt::any>{}(any));
ASSERT_EQ(any.hash(), entt::any{}.hash());
}
TEST_F(MetaAny, TryCast) {
entt::meta_any any{fat_t{}};