meta: meta container support review
This commit is contained in:
2
TODO
2
TODO
@@ -31,3 +31,5 @@ Next:
|
||||
- use a dedicate class template to specialize meta views for a better support to customizations
|
||||
- add const meta container support to meta any
|
||||
- meta_any deref fails if operator* returns a temporary
|
||||
- remove container detector from type traits (is broken)
|
||||
- remove dereferenceable detector from type traits (is broken)
|
||||
|
||||
@@ -20,6 +20,7 @@
|
||||
#include "entity/utility.hpp"
|
||||
#include "entity/view.hpp"
|
||||
#include "locator/locator.hpp"
|
||||
#include "meta/container.hpp"
|
||||
#include "meta/ctx.hpp"
|
||||
#include "meta/factory.hpp"
|
||||
#include "meta/internal.hpp"
|
||||
@@ -27,6 +28,7 @@
|
||||
#include "meta/policy.hpp"
|
||||
#include "meta/range.hpp"
|
||||
#include "meta/resolve.hpp"
|
||||
#include "meta/type_traits.hpp"
|
||||
#include "process/process.hpp"
|
||||
#include "process/scheduler.hpp"
|
||||
#include "resource/cache.hpp"
|
||||
|
||||
541
src/entt/meta/container.hpp
Normal file
541
src/entt/meta/container.hpp
Normal file
@@ -0,0 +1,541 @@
|
||||
#ifndef ENTT_META_CONTAINER_HPP
|
||||
#define ENTT_META_CONTAINER_HPP
|
||||
|
||||
|
||||
#include <array>
|
||||
#include <map>
|
||||
#include <set>
|
||||
#include <unordered_map>
|
||||
#include <unordered_set>
|
||||
#include <utility>
|
||||
#include <vector>
|
||||
#include "../config/config.h"
|
||||
#include "type_traits.hpp"
|
||||
|
||||
|
||||
namespace entt {
|
||||
|
||||
|
||||
/**
|
||||
* @brief Meta sequence container traits for `std::vector`s of any type.
|
||||
* @tparam Type The type of elements.
|
||||
* @tparam Args Other arguments.
|
||||
*/
|
||||
template<typename Type, typename... Args>
|
||||
struct meta_sequence_container_traits_t<std::vector<Type, Args...>> {
|
||||
/*! @brief Iterator type of the sequence container. */
|
||||
using iterator = typename std::vector<Type, Args...>::iterator;
|
||||
/*! @brief Unsigned integer type. */
|
||||
using size_type = typename std::vector<Type, Args...>::size_type;
|
||||
/*! @brief Value type of the sequence container. */
|
||||
using value_type = typename std::vector<Type, Args...>::value_type;
|
||||
|
||||
/**
|
||||
* @brief Returns the size of given a container.
|
||||
* @param vec The container of which to return the size.
|
||||
* @return The size of the given container.
|
||||
*/
|
||||
[[nodiscard]] static size_type size(const std::vector<Type, Args...> &vec) ENTT_NOEXCEPT {
|
||||
return vec.size();
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Clears the content of a given container.
|
||||
* @param vec The container of which to clear the content.
|
||||
* @return True in case of success, false otherwise.
|
||||
*/
|
||||
[[nodiscard]] static bool clear(std::vector<Type, Args...> &vec) {
|
||||
return vec.clear(), true;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Returns an iterator to the first element of a given container.
|
||||
* @param vec The container of which to return the iterator.
|
||||
* @return An iterator to the first element of the given container.
|
||||
*/
|
||||
[[nodiscard]] static iterator begin(std::vector<Type, Args...> &vec) {
|
||||
return vec.begin();
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Returns an iterator past the last element of a given container.
|
||||
* @param vec The container of which to return the iterator.
|
||||
* @return An iterator past the last element of the given container.
|
||||
*/
|
||||
[[nodiscard]] static iterator end(std::vector<Type, Args...> &vec) {
|
||||
return vec.end();
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Inserts an element at a specified location of a given container.
|
||||
* @param vec The container in which to insert the element.
|
||||
* @param it Iterator before which the element will be inserted.
|
||||
* @param value Element value to insert.
|
||||
* @return A pair consisting of an iterator to the inserted element (in case
|
||||
* of success) and a bool denoting whether the insertion took place.
|
||||
*/
|
||||
[[nodiscard]] static std::pair<iterator, bool> insert(std::vector<Type, Args...> &vec, iterator it, const Type &value) {
|
||||
return { vec.insert(it, value), true };
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Removes the specified element from a given container.
|
||||
* @param vec The container from which to remove the element.
|
||||
* @param it Iterator to the element to remove.
|
||||
* @return A pair consisting of an iterator following the last removed
|
||||
* element (in case of success) and a bool denoting whether the insertion
|
||||
* took place.
|
||||
*/
|
||||
[[nodiscard]] static std::pair<iterator, bool> erase(std::vector<Type, Args...> &vec, iterator it) {
|
||||
return { vec.erase(it), true };
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Returns a reference to the element at a specified location of a
|
||||
* given container (no bounds checking is performed).
|
||||
* @param vec The container from which to get the element.
|
||||
* @param pos The position of the element to return.
|
||||
* @return A reference to the requested element.
|
||||
*/
|
||||
[[nodiscard]] static Type & get(std::vector<Type, Args...> &vec, size_type pos) {
|
||||
return vec[pos];
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* @brief Meta sequence container traits for `std::array`s of any type.
|
||||
* @tparam Type The type of elements.
|
||||
* @tparam N The number of elements.
|
||||
*/
|
||||
template<typename Type, auto N>
|
||||
struct meta_sequence_container_traits_t<std::array<Type, N>> {
|
||||
/*! @brief Iterator type of the sequence container. */
|
||||
using iterator = typename std::array<Type, N>::iterator;
|
||||
/*! @brief Unsigned integer type. */
|
||||
using size_type = typename std::array<Type, N>::size_type;
|
||||
/*! @brief Value type of the sequence container. */
|
||||
using value_type = typename std::array<Type, N>::value_type;
|
||||
|
||||
/**
|
||||
* @brief Returns the size of given a container.
|
||||
* @param arr The container of which to return the size.
|
||||
* @return The size of the given container.
|
||||
*/
|
||||
[[nodiscard]] static size_type size(const std::array<Type, N> &arr) ENTT_NOEXCEPT {
|
||||
return arr.size();
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Does nothing.
|
||||
* @return False to indicate failure in all cases.
|
||||
*/
|
||||
[[nodiscard]] static bool clear(std::array<Type, N> &) {
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Returns an iterator to the first element of a given container.
|
||||
* @param arr The container of which to return the iterator.
|
||||
* @return An iterator to the first element of the given container.
|
||||
*/
|
||||
[[nodiscard]] static iterator begin(std::array<Type, N> &arr) {
|
||||
return arr.begin();
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Returns an iterator past the last element of a given container.
|
||||
* @param arr The container of which to return the iterator.
|
||||
* @return An iterator past the last element of the given container.
|
||||
*/
|
||||
[[nodiscard]] static iterator end(std::array<Type, N> &arr) {
|
||||
return arr.end();
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Does nothing.
|
||||
* @return A pair consisting of an invalid iterator and a false value to
|
||||
* indicate failure in all cases.
|
||||
*/
|
||||
[[nodiscard]] static std::pair<iterator, bool> insert(std::array<Type, N> &, iterator, const Type &) {
|
||||
return { {}, false };
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Does nothing.
|
||||
* @return A pair consisting of an invalid iterator and a false value to
|
||||
* indicate failure in all cases.
|
||||
*/
|
||||
[[nodiscard]] static std::pair<iterator, bool> erase(std::array<Type, N> &, iterator) {
|
||||
return { {}, false };
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Returns a reference to the element at a specified location of a
|
||||
* given container (no bounds checking is performed).
|
||||
* @param arr The container from which to get the element.
|
||||
* @param pos The position of the element to return.
|
||||
* @return A reference to the requested element.
|
||||
*/
|
||||
[[nodiscard]] static Type & get(std::array<Type, N> &arr, size_type pos) {
|
||||
return arr[pos];
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* @brief Meta associative container traits for `std::map`s of any type.
|
||||
* @tparam Key The key type of elements.
|
||||
* @tparam Value The value type of elements.
|
||||
* @tparam Args Other arguments.
|
||||
*/
|
||||
template<typename Key, typename Value, typename... Args>
|
||||
struct meta_associative_container_traits_t<std::map<Key, Value, Args...>> {
|
||||
/*! @brief Iterator type of the associative container. */
|
||||
using iterator = typename std::map<Key, Value, Args...>::iterator;
|
||||
/*! @brief Unsigned integer type. */
|
||||
using size_type = typename std::map<Key, Value, Args...>::size_type;
|
||||
/*! @brief Key type of the sequence container. */
|
||||
using key_type = typename std::map<Key, Value, Args...>::key_type;
|
||||
/*! @brief Mapped type of the sequence container. */
|
||||
using mapped_type = typename std::map<Key, Value, Args...>::mapped_type;
|
||||
/*! @brief Value type of the sequence container. */
|
||||
using value_type = typename std::map<Key, Value, Args...>::value_type;
|
||||
|
||||
/**
|
||||
* @brief Returns the size of given a container.
|
||||
* @param map The container of which to return the size.
|
||||
* @return The size of the given container.
|
||||
*/
|
||||
[[nodiscard]] static size_type size(const std::map<Key, Value, Args...> &map) ENTT_NOEXCEPT {
|
||||
return map.size();
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Clears the content of a given container.
|
||||
* @param map The container of which to clear the content.
|
||||
* @return True in case of success, false otherwise.
|
||||
*/
|
||||
[[nodiscard]] static bool clear(std::map<Key, Value, Args...> &map) {
|
||||
return map.clear(), true;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Returns an iterator to the first element of a given container.
|
||||
* @param map The container of which to return the iterator.
|
||||
* @return An iterator to the first element of the given container.
|
||||
*/
|
||||
[[nodiscard]] static iterator begin(std::map<Key, Value, Args...> &map) {
|
||||
return map.begin();
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Returns an iterator past the last element of a given container.
|
||||
* @param map The container of which to return the iterator.
|
||||
* @return An iterator past the last element of the given container.
|
||||
*/
|
||||
[[nodiscard]] static iterator end(std::map<Key, Value, Args...> &map) {
|
||||
return map.end();
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Inserts an element (a key/value pair) into a given container.
|
||||
* @param map The container in which to insert the element.
|
||||
* @param key The key of the element to insert.
|
||||
* @param value The value of the element to insert.
|
||||
* @return A bool denoting whether the insertion took place.
|
||||
*/
|
||||
[[nodiscard]] static bool insert(std::map<Key, Value, Args...> &map, const key_type &key, const mapped_type &value) {
|
||||
return map.insert(std::make_pair(key, value)).second;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Removes the specified element from a given container.
|
||||
* @param map The container from which to remove the element.
|
||||
* @param key The key of the element to remove.
|
||||
* @return A bool denoting whether the removal took place.
|
||||
*/
|
||||
[[nodiscard]] static bool erase(std::map<Key, Value, Args...> &map, const key_type &key) {
|
||||
const auto sz = map.size();
|
||||
return map.erase(key) != sz;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Returns an iterator to the element with key equivalent to a given
|
||||
* one, if any.
|
||||
* @param map The container in which to search for the element.
|
||||
* @param key The key of the element to search.
|
||||
* @return An iterator to the element with the given key, if any.
|
||||
*/
|
||||
[[nodiscard]] static iterator find(std::map<Key, Value, Args...> &map, const key_type &key) {
|
||||
return map.find(key);
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* @brief Meta associative container traits for `std::unordered_map`s of any
|
||||
* type.
|
||||
* @tparam Key The key type of elements.
|
||||
* @tparam Value The value type of elements.
|
||||
* @tparam Args Other arguments.
|
||||
*/
|
||||
template<typename Key, typename Value, typename... Args>
|
||||
struct meta_associative_container_traits_t<std::unordered_map<Key, Value, Args...>> {
|
||||
/*! @brief Iterator type of the associative container. */
|
||||
using iterator = typename std::unordered_map<Key, Value, Args...>::iterator;
|
||||
/*! @brief Unsigned integer type. */
|
||||
using size_type = typename std::unordered_map<Key, Value, Args...>::size_type;
|
||||
/*! @brief Key type of the sequence container. */
|
||||
using key_type = typename std::unordered_map<Key, Value, Args...>::key_type;
|
||||
/*! @brief Mapped type of the sequence container. */
|
||||
using mapped_type = typename std::unordered_map<Key, Value, Args...>::mapped_type;
|
||||
/*! @brief Value type of the sequence container. */
|
||||
using value_type = typename std::unordered_map<Key, Value, Args...>::value_type;
|
||||
|
||||
/**
|
||||
* @brief Returns the size of given a container.
|
||||
* @param map The container of which to return the size.
|
||||
* @return The size of the given container.
|
||||
*/
|
||||
[[nodiscard]] static size_type size(const std::unordered_map<Key, Value, Args...> &map) ENTT_NOEXCEPT {
|
||||
return map.size();
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Clears the content of a given container.
|
||||
* @param map The container of which to clear the content.
|
||||
* @return True in case of success, false otherwise.
|
||||
*/
|
||||
[[nodiscard]] static bool clear(std::unordered_map<Key, Value, Args...> &map) {
|
||||
return map.clear(), true;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Returns an iterator to the first element of a given container.
|
||||
* @param map The container of which to return the iterator.
|
||||
* @return An iterator to the first element of the given container.
|
||||
*/
|
||||
[[nodiscard]] static iterator begin(std::unordered_map<Key, Value, Args...> &map) {
|
||||
return map.begin();
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Returns an iterator past the last element of a given container.
|
||||
* @param map The container of which to return the iterator.
|
||||
* @return An iterator past the last element of the given container.
|
||||
*/
|
||||
[[nodiscard]] static iterator end(std::unordered_map<Key, Value, Args...> &map) {
|
||||
return map.end();
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Inserts an element (a key/value pair) into a given container.
|
||||
* @param map The container in which to insert the element.
|
||||
* @param key The key of the element to insert.
|
||||
* @param value The value of the element to insert.
|
||||
* @return A bool denoting whether the insertion took place.
|
||||
*/
|
||||
[[nodiscard]] static bool insert(std::unordered_map<Key, Value, Args...> &map, const key_type &key, const mapped_type &value) {
|
||||
return map.insert(std::make_pair(key, value)).second;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Removes the specified element from a given container.
|
||||
* @param map The container from which to remove the element.
|
||||
* @param key The key of the element to remove.
|
||||
* @return A bool denoting whether the removal took place.
|
||||
*/
|
||||
[[nodiscard]] static bool erase(std::unordered_map<Key, Value, Args...> &map, const key_type &key) {
|
||||
const auto sz = map.size();
|
||||
return map.erase(key) != sz;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Returns an iterator to the element with key equivalent to a given
|
||||
* one, if any.
|
||||
* @param map The container in which to search for the element.
|
||||
* @param key The key of the element to search.
|
||||
* @return An iterator to the element with the given key, if any.
|
||||
*/
|
||||
[[nodiscard]] static iterator find(std::unordered_map<Key, Value, Args...> &map, const key_type &key) {
|
||||
return map.find(key);
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* @brief Meta associative container traits for `std::set`s of any type.
|
||||
* @tparam Key The type of elements.
|
||||
* @tparam Args Other arguments.
|
||||
*/
|
||||
template<typename Key, typename... Args>
|
||||
struct meta_associative_container_traits_t<std::set<Key, Args...>> {
|
||||
/*! @brief Iterator type of the associative container. */
|
||||
using iterator = typename std::set<Key, Args...>::iterator;
|
||||
/*! @brief Unsigned integer type. */
|
||||
using size_type = typename std::set<Key, Args...>::size_type;
|
||||
/*! @brief Key type of the sequence container. */
|
||||
using key_type = typename std::set<Key, Args...>::key_type;
|
||||
/*! @brief Value type of the sequence container. */
|
||||
using value_type = typename std::set<Key, Args...>::value_type;
|
||||
|
||||
/**
|
||||
* @brief Returns the size of given a container.
|
||||
* @param set The container of which to return the size.
|
||||
* @return The size of the given container.
|
||||
*/
|
||||
[[nodiscard]] static size_type size(const std::set<Key, Args...> &set) ENTT_NOEXCEPT {
|
||||
return set.size();
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Clears the content of a given container.
|
||||
* @param set The container of which to clear the content.
|
||||
* @return True in case of success, false otherwise.
|
||||
*/
|
||||
[[nodiscard]] static bool clear(std::set<Key, Args...> &set) {
|
||||
return set.clear(), true;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Returns an iterator to the first element of a given container.
|
||||
* @param set The container of which to return the iterator.
|
||||
* @return An iterator to the first element of the given container.
|
||||
*/
|
||||
[[nodiscard]] static iterator begin(std::set<Key, Args...> &set) {
|
||||
return set.begin();
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Returns an iterator past the last element of a given container.
|
||||
* @param set The container of which to return the iterator.
|
||||
* @return An iterator past the last element of the given container.
|
||||
*/
|
||||
[[nodiscard]] static iterator end(std::set<Key, Args...> &set) {
|
||||
return set.end();
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Inserts an element into a given container.
|
||||
* @param set The container in which to insert the element.
|
||||
* @param key The element to insert.
|
||||
* @return A bool denoting whether the insertion took place.
|
||||
*/
|
||||
[[nodiscard]] static bool insert(std::set<Key, Args...> &set, const key_type &key) {
|
||||
return set.insert(key).second;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Removes the specified element from a given container.
|
||||
* @param set The container from which to remove the element.
|
||||
* @param key The element to remove.
|
||||
* @return A bool denoting whether the removal took place.
|
||||
*/
|
||||
[[nodiscard]] static bool erase(std::set<Key, Args...> &set, const key_type &key) {
|
||||
const auto sz = set.size();
|
||||
return set.erase(key) != sz;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Returns an iterator to a given element, if any.
|
||||
* @param set The container in which to search for the element.
|
||||
* @param key The element to search.
|
||||
* @return An iterator to the given element, if any.
|
||||
*/
|
||||
[[nodiscard]] static iterator find(std::set<Key, Args...> &set, const key_type &key) {
|
||||
return set.find(key);
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* @brief Meta associative container traits for `std::unordered_set`s of any
|
||||
* type.
|
||||
* @tparam Key The type of elements.
|
||||
* @tparam Args Other arguments.
|
||||
*/
|
||||
template<typename Key, typename... Args>
|
||||
struct meta_associative_container_traits_t<std::unordered_set<Key, Args...>> {
|
||||
/*! @brief Iterator type of the associative container. */
|
||||
using iterator = typename std::unordered_set<Key, Args...>::iterator;
|
||||
/*! @brief Unsigned integer type. */
|
||||
using size_type = typename std::unordered_set<Key, Args...>::size_type;
|
||||
/*! @brief Key type of the sequence container. */
|
||||
using key_type = typename std::unordered_set<Key, Args...>::key_type;
|
||||
/*! @brief Value type of the sequence container. */
|
||||
using value_type = typename std::unordered_set<Key, Args...>::value_type;
|
||||
|
||||
/**
|
||||
* @brief Returns the size of given a container.
|
||||
* @param set The container of which to return the size.
|
||||
* @return The size of the given container.
|
||||
*/
|
||||
[[nodiscard]] static size_type size(const std::unordered_set<Key, Args...> &set) ENTT_NOEXCEPT {
|
||||
return set.size();
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Clears the content of a given container.
|
||||
* @param set The container of which to clear the content.
|
||||
* @return True in case of success, false otherwise.
|
||||
*/
|
||||
[[nodiscard]] static bool clear(std::unordered_set<Key, Args...> &set) {
|
||||
return set.clear(), true;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Returns an iterator to the first element of a given container.
|
||||
* @param set The container of which to return the iterator.
|
||||
* @return An iterator to the first element of the given container.
|
||||
*/
|
||||
[[nodiscard]] static iterator begin(std::unordered_set<Key, Args...> &set) {
|
||||
return set.begin();
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Returns an iterator past the last element of a given container.
|
||||
* @param set The container of which to return the iterator.
|
||||
* @return An iterator past the last element of the given container.
|
||||
*/
|
||||
[[nodiscard]] static iterator end(std::unordered_set<Key, Args...> &set) {
|
||||
return set.end();
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Inserts an element into a given container.
|
||||
* @param set The container in which to insert the element.
|
||||
* @param key The element to insert.
|
||||
* @return A bool denoting whether the insertion took place.
|
||||
*/
|
||||
[[nodiscard]] static bool insert(std::unordered_set<Key, Args...> &set, const key_type &key) {
|
||||
return set.insert(key).second;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Removes the specified element from a given container.
|
||||
* @param set The container from which to remove the element.
|
||||
* @param key The element to remove.
|
||||
* @return A bool denoting whether the removal took place.
|
||||
*/
|
||||
[[nodiscard]] static bool erase(std::unordered_set<Key, Args...> &set, const key_type &key) {
|
||||
const auto sz = set.size();
|
||||
return set.erase(key) != sz;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Returns an iterator to a given element, if any.
|
||||
* @param set The container in which to search for the element.
|
||||
* @param key The element to search.
|
||||
* @return An iterator to the given element, if any.
|
||||
*/
|
||||
[[nodiscard]] static iterator find(std::unordered_set<Key, Args...> &set, const key_type &key) {
|
||||
return set.find(key);
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
}
|
||||
|
||||
|
||||
#endif
|
||||
@@ -12,6 +12,7 @@
|
||||
#include "../core/fwd.hpp"
|
||||
#include "../core/type_info.hpp"
|
||||
#include "../core/type_traits.hpp"
|
||||
#include "type_traits.hpp"
|
||||
|
||||
|
||||
namespace entt {
|
||||
@@ -419,8 +420,8 @@ public:
|
||||
std::is_member_object_pointer_v<Type>,
|
||||
std::is_member_function_pointer_v<Type>,
|
||||
is_dereferenceable_v<Type>,
|
||||
is_sequence_container_v<Type>,
|
||||
is_associative_container_v<Type>,
|
||||
has_meta_sequence_container_traits_v<Type>,
|
||||
has_meta_associative_container_traits_v<Type>,
|
||||
std::rank_v<Type>,
|
||||
[](meta_type_node::size_type dim) {
|
||||
return extent(dim, std::make_index_sequence<std::rank_v<Type>>{});
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
78
src/entt/meta/type_traits.hpp
Normal file
78
src/entt/meta/type_traits.hpp
Normal file
@@ -0,0 +1,78 @@
|
||||
#ifndef ENTT_META_TYPE_TRAITS_HPP
|
||||
#define ENTT_META_TYPE_TRAITS_HPP
|
||||
|
||||
|
||||
#include <type_traits>
|
||||
|
||||
|
||||
namespace entt {
|
||||
|
||||
|
||||
/**
|
||||
* @brief Traits class template to be specialized to enable support for meta
|
||||
* sequence containers.
|
||||
*/
|
||||
template<typename>
|
||||
struct meta_sequence_container_traits_t;
|
||||
|
||||
|
||||
/**
|
||||
* @brief Traits class template to be specialized to enable support for meta
|
||||
* associative containers.
|
||||
*/
|
||||
template<typename>
|
||||
struct meta_associative_container_traits_t;
|
||||
|
||||
|
||||
/**
|
||||
* @brief Provides the member constant `value` to true if support for meta
|
||||
* sequence containers is enabled for the given type, false otherwise.
|
||||
* @tparam Type Potentially sequence container type.
|
||||
*/
|
||||
template<typename Type, typename = void>
|
||||
struct has_meta_sequence_container_traits: std::false_type {};
|
||||
|
||||
|
||||
/*! @copydoc has_meta_sequence_container_traits */
|
||||
template<typename Type>
|
||||
struct has_meta_sequence_container_traits<Type, std::void_t<typename meta_sequence_container_traits_t<Type>::value_type>>
|
||||
: std::true_type
|
||||
{};
|
||||
|
||||
|
||||
/**
|
||||
* @brief Helper variable template.
|
||||
* @tparam Type Potentially sequence container type.
|
||||
*/
|
||||
template<typename Type>
|
||||
inline constexpr auto has_meta_sequence_container_traits_v = has_meta_sequence_container_traits<Type>::value;
|
||||
|
||||
|
||||
/**
|
||||
* @brief Provides the member constant `value` to true if support for meta
|
||||
* associative containers is enabled for the given type, false otherwise.
|
||||
* @tparam Type Potentially associative container type.
|
||||
*/
|
||||
template<typename, typename = void>
|
||||
struct has_meta_associative_container_traits: std::false_type {};
|
||||
|
||||
|
||||
/*! @copydoc has_meta_associative_container_traits */
|
||||
template<typename Type>
|
||||
struct has_meta_associative_container_traits<Type, std::void_t<typename meta_associative_container_traits_t<Type>::key_type>>
|
||||
: std::true_type
|
||||
{};
|
||||
|
||||
|
||||
/**
|
||||
* @brief Helper variable template.
|
||||
* @tparam Type Potentially associative container type.
|
||||
*/
|
||||
template<typename Type>
|
||||
inline constexpr auto has_meta_associative_container_traits_v = has_meta_associative_container_traits<Type>::value;
|
||||
|
||||
|
||||
}
|
||||
|
||||
|
||||
#endif
|
||||
@@ -1,32 +1,30 @@
|
||||
#include <array>
|
||||
#include <map>
|
||||
#include <set>
|
||||
#include <utility>
|
||||
#include <vector>
|
||||
#include <gtest/gtest.h>
|
||||
#include <entt/core/hashed_string.hpp>
|
||||
#include <entt/meta/container.hpp>
|
||||
#include <entt/meta/factory.hpp>
|
||||
#include <entt/meta/meta.hpp>
|
||||
#include <entt/meta/resolve.hpp>
|
||||
#include <entt/meta/type_traits.hpp>
|
||||
|
||||
TEST(MetaContainer, Empty) {
|
||||
entt::meta_container container{};
|
||||
TEST(MetaSequenceContainer, Empty) {
|
||||
entt::meta_sequence_container container{};
|
||||
|
||||
ASSERT_FALSE(container);
|
||||
|
||||
entt::meta_any any{std::vector<int>{}};
|
||||
container = any.view();
|
||||
container = any.as_sequence_container();
|
||||
|
||||
ASSERT_TRUE(container);
|
||||
}
|
||||
|
||||
TEST(MetaContainer, DynamicSequenceContainer) {
|
||||
TEST(MetaSequenceContainer, StdVector) {
|
||||
std::vector<int> vec{2, 3, 4};
|
||||
entt::meta_any any{std::ref(vec)};
|
||||
|
||||
auto view = any.view();
|
||||
auto view = any.as_sequence_container();
|
||||
|
||||
ASSERT_TRUE(view);
|
||||
ASSERT_EQ(view.value_type(), entt::resolve<int>());
|
||||
ASSERT_EQ(view.size(), 3u);
|
||||
|
||||
auto first = view.begin();
|
||||
@@ -44,35 +42,39 @@ TEST(MetaContainer, DynamicSequenceContainer) {
|
||||
ASSERT_TRUE(first == last);
|
||||
ASSERT_FALSE(first != last);
|
||||
|
||||
ASSERT_EQ((*view[std::size_t{1u}]).cast<int>(), 3);
|
||||
ASSERT_EQ(view[1u].cast<int>(), 3);
|
||||
|
||||
auto it = view.begin();
|
||||
auto ret = view.insert(it, 0);
|
||||
|
||||
ASSERT_TRUE(view.insert(it.handle(), 0));
|
||||
ASSERT_TRUE(view.insert((++it).handle(), 1));
|
||||
ASSERT_TRUE(ret.second);
|
||||
ASSERT_FALSE(view.insert(ret.first, 'c').second);
|
||||
ASSERT_TRUE(view.insert(++ret.first, 1).second);
|
||||
|
||||
ASSERT_EQ(view.size(), 5u);
|
||||
ASSERT_EQ((*view.begin()).cast<int>(), 0);
|
||||
ASSERT_EQ((*++view.begin()).cast<int>(), 1);
|
||||
|
||||
it = view.begin();
|
||||
ret = view.erase(it);
|
||||
|
||||
ASSERT_TRUE(view.erase(it.handle()));
|
||||
ASSERT_TRUE(ret.second);
|
||||
ASSERT_EQ(view.size(), 4u);
|
||||
ASSERT_EQ((*it).cast<int>(), 1);
|
||||
ASSERT_EQ((*ret.first).cast<int>(), 1);
|
||||
|
||||
(*view[std::size_t{}]).cast<int>() = 5;
|
||||
view[0].cast<int>() = 5;
|
||||
|
||||
ASSERT_EQ((*view.begin()).cast<int>(), 5);
|
||||
}
|
||||
|
||||
TEST(MetaContainer, FixedSizeSequenceContainer) {
|
||||
TEST(MetaSequenceContainer, StdArray) {
|
||||
std::array<int, 3> arr{2, 3, 4};
|
||||
entt::meta_any any{std::ref(arr)};
|
||||
|
||||
auto view = any.view();
|
||||
auto view = any.as_sequence_container();
|
||||
|
||||
ASSERT_TRUE(view);
|
||||
ASSERT_EQ(view.value_type(), entt::resolve<int>());
|
||||
ASSERT_EQ(view.size(), 3u);
|
||||
|
||||
auto first = view.begin();
|
||||
@@ -90,33 +92,37 @@ TEST(MetaContainer, FixedSizeSequenceContainer) {
|
||||
ASSERT_TRUE(first == last);
|
||||
ASSERT_FALSE(first != last);
|
||||
|
||||
ASSERT_EQ((*view[std::size_t{1u}]).cast<int>(), 3);
|
||||
ASSERT_EQ(view[1u].cast<int>(), 3);
|
||||
|
||||
auto it = view.begin();
|
||||
auto ret = view.insert(it, 0);
|
||||
|
||||
ASSERT_FALSE(view.insert(it.handle(), 0));
|
||||
ASSERT_FALSE(view.insert((++it).handle(), 1));
|
||||
ASSERT_FALSE(ret.second);
|
||||
ASSERT_FALSE(view.insert(ret.first, 'c').second);
|
||||
ASSERT_FALSE(view.insert(++ret.first, 1).second);
|
||||
|
||||
ASSERT_EQ(view.size(), 3u);
|
||||
ASSERT_EQ((*view.begin()).cast<int>(), 2);
|
||||
ASSERT_EQ((*++view.begin()).cast<int>(), 3);
|
||||
|
||||
it = view.begin();
|
||||
ret = view.erase(it);
|
||||
|
||||
ASSERT_FALSE(view.erase(it.handle()));
|
||||
|
||||
ASSERT_FALSE(ret.second);
|
||||
ASSERT_EQ(view.size(), 3u);
|
||||
ASSERT_EQ((*it).cast<int>(), 2);
|
||||
|
||||
(*view[std::size_t{}]).cast<int>() = 5;
|
||||
view[0].cast<int>() = 5;
|
||||
|
||||
ASSERT_EQ((*view.begin()).cast<int>(), 5);
|
||||
}
|
||||
|
||||
TEST(MetaContainer, KeyValueAssociativeContainer) {
|
||||
TEST(MetaAssociativeContainer, StdMap) {
|
||||
std::map<int, char> map{{2, 'c'}, {3, 'd'}, {4, 'e'}};
|
||||
entt::meta_any any{std::ref(map)};
|
||||
|
||||
auto view = any.view();
|
||||
auto view = any.as_associative_container();
|
||||
|
||||
ASSERT_TRUE(view);
|
||||
ASSERT_EQ(view.size(), 3u);
|
||||
@@ -136,29 +142,32 @@ TEST(MetaContainer, KeyValueAssociativeContainer) {
|
||||
ASSERT_TRUE(first == last);
|
||||
ASSERT_FALSE(first != last);
|
||||
|
||||
ASSERT_EQ(((*view[3]).cast<std::pair<const int, char>>()), (std::pair<const int, char>{3, 'd'}));
|
||||
ASSERT_EQ(((*view.find(3)).cast<std::pair<const int, char>>()), (std::pair<const int, char>{3, 'd'}));
|
||||
|
||||
ASSERT_FALSE(view.insert('a', 'a'));
|
||||
ASSERT_FALSE(view.insert(1, 1));
|
||||
|
||||
ASSERT_TRUE(view.insert(0, 'a'));
|
||||
ASSERT_TRUE(view.insert(1, 'b'));
|
||||
|
||||
ASSERT_EQ(view.size(), 5u);
|
||||
ASSERT_EQ(((*view[0]).cast<std::pair<const int, char>>()), (std::pair<const int, char>{0, 'a'}));
|
||||
ASSERT_EQ(((*view[1]).cast<std::pair<const int, char>>()), (std::pair<const int, char>{1, 'b'}));
|
||||
ASSERT_EQ(((*view.find(0)).cast<std::pair<const int, char>>()), (std::pair<const int, char>{0, 'a'}));
|
||||
ASSERT_EQ(((*view.find(1)).cast<std::pair<const int, char>>()), (std::pair<const int, char>{1, 'b'}));
|
||||
|
||||
ASSERT_TRUE(view.erase(0));
|
||||
ASSERT_EQ(view.size(), 4u);
|
||||
ASSERT_EQ(view[0], view.end());
|
||||
ASSERT_EQ(view.find(0), view.end());
|
||||
|
||||
(*view[1]).cast<std::pair<const int, char>>().second = 'f';
|
||||
(*view.find(1)).cast<std::pair<const int, char>>().second = 'f';
|
||||
|
||||
ASSERT_EQ(((*view[1]).cast<std::pair<const int, char>>()), (std::pair<const int, char>{1, 'f'}));
|
||||
ASSERT_EQ(((*view.find(1)).cast<std::pair<const int, char>>()), (std::pair<const int, char>{1, 'f'}));
|
||||
}
|
||||
|
||||
TEST(MetaContainer, KeyOnlyAssociativeContainer) {
|
||||
TEST(MetaAssociativeContainer, StdSet) {
|
||||
std::set<int> set{2, 3, 4};
|
||||
entt::meta_any any{std::ref(set)};
|
||||
|
||||
auto view = any.view();
|
||||
auto view = any.as_associative_container();
|
||||
|
||||
ASSERT_TRUE(view);
|
||||
ASSERT_EQ(view.size(), 3u);
|
||||
@@ -178,16 +187,22 @@ TEST(MetaContainer, KeyOnlyAssociativeContainer) {
|
||||
ASSERT_TRUE(first == last);
|
||||
ASSERT_FALSE(first != last);
|
||||
|
||||
ASSERT_NE(view[3], view.end());
|
||||
ASSERT_EQ((*view.find(3)).cast<int>(), 3);
|
||||
|
||||
ASSERT_TRUE(view.insert(0, 'a'));
|
||||
ASSERT_FALSE(view.insert('0'));
|
||||
|
||||
ASSERT_TRUE(view.insert(0));
|
||||
ASSERT_TRUE(view.insert(1));
|
||||
|
||||
ASSERT_EQ(view.size(), 5u);
|
||||
ASSERT_NE(view[0], view.end());
|
||||
ASSERT_NE(view[1], view.end());
|
||||
ASSERT_EQ((*view.find(0)).cast<int>(), 0);
|
||||
ASSERT_EQ((*view.find(1)).cast<int>(), 1);
|
||||
|
||||
ASSERT_TRUE(view.erase(0));
|
||||
ASSERT_EQ(view.size(), 4u);
|
||||
ASSERT_EQ(view[0], view.end());
|
||||
ASSERT_EQ(view.find(0), view.end());
|
||||
|
||||
(*view.find(1)).cast<int>() = 42;
|
||||
|
||||
ASSERT_EQ((*view.find(1)).cast<int>(), 1);
|
||||
}
|
||||
|
||||
@@ -6,6 +6,7 @@
|
||||
#include <entt/meta/factory.hpp>
|
||||
#include <entt/meta/meta.hpp>
|
||||
#include <entt/meta/resolve.hpp>
|
||||
#include <entt/meta/container.hpp>
|
||||
|
||||
template<typename Type>
|
||||
void set(Type &prop, Type value) {
|
||||
|
||||
Reference in New Issue
Block a user