meta: minimal (and still inefficient) support for lists as sequence containers

This commit is contained in:
Michele Caini
2022-07-12 11:43:33 +02:00
parent 84cbfb2f91
commit 14ce88730f
4 changed files with 65 additions and 5 deletions

1
TODO
View File

@@ -12,6 +12,7 @@ DOC:
* update entity doc when the storage based model is in place
WIP:
* meta: add deque support as sequence container
* sparse set/storage support for move-only types, internal rework required
* get rid of observers, storage based views made them pointless - document alternatives
* add storage getter for filters to views and groups

View File

@@ -2,6 +2,8 @@
#define ENTT_META_CONTAINER_HPP
#include <array>
#include <iterator>
#include <list>
#include <map>
#include <set>
#include <type_traits>
@@ -70,12 +72,12 @@ struct basic_meta_sequence_container_traits {
// this abomination is necessary because only on macos value_type and const_reference are different types for std::vector<bool>
if(value.allow_cast<typename Type::const_reference>() || value.allow_cast<typename Type::value_type>()) {
const auto *element = value.try_cast<std::remove_reference_t<typename Type::const_reference>>();
const auto curr = cont->insert(cont->begin() + offset, element ? *element : value.cast<typename Type::value_type>());
return iterator{*cont, curr - cont->begin()};
const auto curr = cont->insert(std::next(cont->begin(), offset), element ? *element : value.cast<typename Type::value_type>());
return iterator{*cont, static_cast<std::ptrdiff_t>(offset)};
}
} else {
const auto curr = cont->erase(cont->begin() + offset);
return iterator{*cont, curr - cont->begin()};
const auto curr = cont->erase(std::next(cont->begin(), offset));
return iterator{*cont, static_cast<std::ptrdiff_t>(offset)};
}
}
}
@@ -167,6 +169,15 @@ template<typename Type, auto N>
struct meta_sequence_container_traits<std::array<Type, N>>
: internal::basic_meta_sequence_container_traits<std::array<Type, N>> {};
/**
* @brief Meta sequence container traits for `std::list`s of any type.
* @tparam Type The type of elements.
* @tparam Args Other arguments.
*/
template<typename Type, typename... Args>
struct meta_sequence_container_traits<std::list<Type, Args...>>
: internal::basic_meta_sequence_container_traits<std::list<Type, Args...>> {};
/**
* @brief Meta associative container traits for `std::map`s of any type.
* @tparam Key The key type of elements.

View File

@@ -1471,7 +1471,7 @@ class meta_sequence_container::meta_iterator final {
template<typename It>
static meta_any deref_fn(const any &value, const std::ptrdiff_t pos) {
return meta_any{std::in_place_type<typename std::iterator_traits<It>::reference>, any_cast<const It &>(value)[pos]};
return meta_any{std::in_place_type<typename std::iterator_traits<It>::reference>, *std::next(any_cast<const It &>(value), pos)};
}
public:

View File

@@ -1,4 +1,5 @@
#include <array>
#include <list>
#include <map>
#include <set>
#include <utility>
@@ -204,6 +205,53 @@ TEST_F(MetaContainer, StdArray) {
ASSERT_EQ(view.size(), 3u);
}
TEST_F(MetaContainer, StdList) {
std::list<int> list{};
auto any = entt::forward_as_meta(list);
auto view = any.as_sequence_container();
ASSERT_TRUE(view);
ASSERT_EQ(view.value_type(), entt::resolve<int>());
ASSERT_EQ(view.size(), 0u);
ASSERT_EQ(view.begin(), view.end());
ASSERT_TRUE(view.resize(3u));
ASSERT_EQ(view.size(), 3u);
ASSERT_NE(view.begin(), view.end());
view[0].cast<int &>() = 2;
view[1].cast<int &>() = 3;
view[2].cast<int &>() = 4;
ASSERT_EQ(view[1u].cast<int>(), 3);
auto it = view.begin();
auto ret = view.insert(it, 0);
ASSERT_TRUE(ret);
ASSERT_FALSE(view.insert(ret, invalid_type{}));
ASSERT_TRUE(view.insert(++ret, 1.));
ASSERT_EQ(view.size(), 5u);
ASSERT_EQ(view.begin()->cast<int>(), 0);
ASSERT_EQ((++view.begin())->cast<int>(), 1);
ret = view.insert(view.end(), 42);
ASSERT_TRUE(ret);
ASSERT_EQ(*ret, 42);
it = view.begin();
ret = view.erase(it);
ASSERT_TRUE(ret);
ASSERT_EQ(view.size(), 5u);
ASSERT_EQ(ret->cast<int>(), 1);
ASSERT_TRUE(view.clear());
ASSERT_EQ(view.size(), 0u);
}
TEST_F(MetaContainer, StdMap) {
std::map<int, char> map{{2, 'c'}, {3, 'd'}, {4, 'e'}};
auto any = entt::forward_as_meta(map);