meta_any: ::hash function for hashable types (+ bonus doc review)
This commit is contained in:
1
TODO
1
TODO
@@ -4,6 +4,7 @@
|
||||
* add examples (and credits) from @alanjfs :)
|
||||
|
||||
WIP:
|
||||
* any: avoid operations when trivially-*
|
||||
* runtime events (emitter)
|
||||
* iterator based try_emplace vs try_insert for perf reasons
|
||||
* registry: remove reference to basic_sparse_set<E>
|
||||
|
||||
@@ -2,6 +2,7 @@
|
||||
#define ENTT_META_META_HPP
|
||||
|
||||
#include <cstddef>
|
||||
#include <functional>
|
||||
#include <iterator>
|
||||
#include <memory>
|
||||
#include <type_traits>
|
||||
@@ -283,21 +284,15 @@ public:
|
||||
return *this;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Returns the type of the underlying object.
|
||||
* @return The type of the underlying object, if any.
|
||||
*/
|
||||
/*! @copydoc any::type */
|
||||
[[nodiscard]] inline meta_type type() const ENTT_NOEXCEPT;
|
||||
|
||||
/**
|
||||
* @brief Returns an opaque pointer to the contained instance.
|
||||
* @return An opaque pointer the contained instance, if any.
|
||||
*/
|
||||
/*! @copydoc any::data */
|
||||
[[nodiscard]] const void *data() const ENTT_NOEXCEPT {
|
||||
return storage.data();
|
||||
}
|
||||
|
||||
/*! @copydoc data */
|
||||
/*! @copydoc any::data */
|
||||
[[nodiscard]] void *data() ENTT_NOEXCEPT {
|
||||
return storage.data();
|
||||
}
|
||||
@@ -469,12 +464,7 @@ public:
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Replaces the contained object by creating a new instance directly.
|
||||
* @tparam Type Type of object to use to initialize the wrapper.
|
||||
* @tparam Args Types of arguments to use to construct the new instance.
|
||||
* @param args Parameters to use to construct the instance.
|
||||
*/
|
||||
/*! @copydoc any::emplace */
|
||||
template<typename Type, typename... Args>
|
||||
void emplace(Args &&...args) {
|
||||
release();
|
||||
@@ -483,21 +473,13 @@ public:
|
||||
node = internal::meta_node<std::remove_const_t<std::remove_reference_t<Type>>>::resolve();
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Copy assigns a value to the contained object without replacing it.
|
||||
* @param other The value to assign to the contained object.
|
||||
* @return True in case of success, false otherwise.
|
||||
*/
|
||||
/*! @copydoc any::assign */
|
||||
bool assign(const meta_any &other);
|
||||
|
||||
/**
|
||||
* @brief Move assigns a value to the contained object without replacing it.
|
||||
* @param other The value to assign to the contained object.
|
||||
* @return True in case of success, false otherwise.
|
||||
*/
|
||||
/*! @copydoc any::assign */
|
||||
bool assign(meta_any &&other);
|
||||
|
||||
/*! @brief Destroys contained object */
|
||||
/*! @copydoc any::reset */
|
||||
void reset() {
|
||||
release();
|
||||
vtable = &basic_vtable<void>;
|
||||
@@ -562,36 +544,31 @@ public:
|
||||
return !(node == nullptr);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Checks if two wrappers differ in their content.
|
||||
* @param other Wrapper with which to compare.
|
||||
* @return False if the two objects differ in their content, true otherwise.
|
||||
*/
|
||||
/*! @copydoc any::operator== */
|
||||
[[nodiscard]] bool operator==(const meta_any &other) const {
|
||||
return (!node && !other.node) || (node && other.node && *node->info == *other.node->info && storage == other.storage);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Aliasing constructor.
|
||||
* @return A wrapper that shares a reference to an unmanaged object.
|
||||
*/
|
||||
/*! @copydoc any::as_ref */
|
||||
[[nodiscard]] meta_any as_ref() ENTT_NOEXCEPT {
|
||||
return meta_any{*this, storage.as_ref()};
|
||||
}
|
||||
|
||||
/*! @copydoc as_ref */
|
||||
/*! @copydoc any::as_ref */
|
||||
[[nodiscard]] meta_any as_ref() const ENTT_NOEXCEPT {
|
||||
return meta_any{*this, storage.as_ref()};
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Returns true if a wrapper owns its object, false otherwise.
|
||||
* @return True if the wrapper owns its object, false otherwise.
|
||||
*/
|
||||
/*! @copydoc any::owner */
|
||||
[[nodiscard]] bool owner() const ENTT_NOEXCEPT {
|
||||
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;
|
||||
@@ -1867,4 +1844,21 @@ 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
|
||||
|
||||
@@ -1076,6 +1076,33 @@ 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<std::nullptr_t>{}({}));
|
||||
ASSERT_EQ(std::hash<std::nullptr_t>{}({}), 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