any/meta_any: revert changes to introduce ::hash
This commit is contained in:
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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.
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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>);
|
||||
|
||||
@@ -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{}};
|
||||
|
||||
|
||||
Reference in New Issue
Block a user