meta: meta container support review

This commit is contained in:
Michele Caini
2020-06-19 18:32:52 +02:00
parent 4e66fb4589
commit 8a344cd9b2
8 changed files with 1293 additions and 414 deletions

2
TODO
View File

@@ -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)

View File

@@ -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
View 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

View File

@@ -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

View 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

View File

@@ -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);
}

View File

@@ -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) {