view: support converting views
This commit is contained in:
1
TODO
1
TODO
@@ -32,4 +32,3 @@ TODO:
|
||||
* archetype-like a-là EnTT support (see my own notes)
|
||||
* meta: conversion_helper machinery has lot of room for improvements
|
||||
* organizer: view/storage only based model, no registry
|
||||
* view conversion function (i.e. view<T, const U, V> -> view<const T, V>)
|
||||
|
||||
@@ -457,6 +457,13 @@ class basic_view<get_t<Get...>, exclude_t<Exclude...>, std::enable_if_t<(sizeof.
|
||||
}
|
||||
}
|
||||
|
||||
template<typename Type>
|
||||
void storage_if(Type *elem) noexcept {
|
||||
if(elem != nullptr) {
|
||||
storage<index_of<typename Type::element_type>>(*elem);
|
||||
}
|
||||
}
|
||||
|
||||
public:
|
||||
/*! @brief Common type among all storage types. */
|
||||
using common_type = base_type::common_type;
|
||||
@@ -492,6 +499,18 @@ public:
|
||||
basic_view(std::tuple<Get &...> value, std::tuple<Exclude &...> excl = {}) noexcept
|
||||
: basic_view{std::make_from_tuple<basic_view>(std::tuple_cat(value, excl))} {}
|
||||
|
||||
/**
|
||||
* @brief Constructs a view from a convertible counterpart.
|
||||
* @tparam Args Storage types managed by the other view.
|
||||
* @param other A view to convert from.
|
||||
*/
|
||||
template<typename... Args, typename = std::enable_if_t<!std::is_same_v<basic_view, basic_view<Args...>>>>
|
||||
basic_view(const basic_view<Args...> &other) noexcept
|
||||
: basic_view{} {
|
||||
(storage_if(other.storage<typename Get::element_type>()), ...);
|
||||
(storage_if(other.storage<typename Exclude::element_type>()), ...);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Forces a view to use a given element to drive iterations
|
||||
* @tparam Type Type of element to use to drive iterations.
|
||||
|
||||
@@ -682,6 +682,54 @@ TEST(MultiStorageView, Functionalities) {
|
||||
ASSERT_FALSE(invalid);
|
||||
}
|
||||
|
||||
TEST(MultiStorageView, Conversion) {
|
||||
entt::basic_view<entt::get_t<entt::storage<int>, const entt::storage<char>>, entt::exclude_t<entt::storage<double>, const entt::storage<float>>> view1{};
|
||||
entt::basic_view<entt::get_t<const entt::storage<int>, const entt::storage<char>>, entt::exclude_t<const entt::storage<double>, const entt::storage<float>>> view2{view1};
|
||||
entt::basic_view<entt::get_t<entt::storage<int>>, entt::exclude_t<const entt::storage<double>>> view3{view1};
|
||||
entt::basic_view<entt::get_t<const entt::storage<char>>, entt::exclude_t<>> view4{view1};
|
||||
|
||||
ASSERT_FALSE(view1);
|
||||
ASSERT_FALSE(view2);
|
||||
ASSERT_FALSE(view3);
|
||||
ASSERT_FALSE(view4);
|
||||
|
||||
entt::storage<int> istorage{};
|
||||
entt::storage<char> cstorage{};
|
||||
entt::storage<double> dstorage{};
|
||||
entt::storage<float> fstorage{};
|
||||
|
||||
view1.storage(istorage);
|
||||
view1.storage(cstorage);
|
||||
view1.storage(dstorage);
|
||||
view1.storage(fstorage);
|
||||
|
||||
view2 = view1;
|
||||
view3 = view1;
|
||||
view4 = view1;
|
||||
|
||||
ASSERT_TRUE(view1);
|
||||
ASSERT_TRUE(view2);
|
||||
ASSERT_TRUE(view3);
|
||||
ASSERT_TRUE(view4);
|
||||
|
||||
ASSERT_EQ(0u, view1.size_hint());
|
||||
ASSERT_EQ(0u, view2.size_hint());
|
||||
ASSERT_EQ(0u, view3.size_hint());
|
||||
ASSERT_EQ(0u, view4.size());
|
||||
|
||||
const entt::entity entity{1};
|
||||
|
||||
istorage.emplace(entity);
|
||||
cstorage.emplace(entity);
|
||||
dstorage.emplace(entity);
|
||||
fstorage.emplace(entity);
|
||||
|
||||
ASSERT_EQ(1u, view1.size_hint());
|
||||
ASSERT_EQ(1u, view2.size_hint());
|
||||
ASSERT_EQ(1u, view3.size_hint());
|
||||
ASSERT_EQ(1u, view4.size());
|
||||
}
|
||||
|
||||
TEST(MultiStorageView, InvalidView) {
|
||||
entt::basic_view<entt::get_t<entt::storage<int>>, entt::exclude_t<entt::storage<char>>> view{};
|
||||
auto iterable = view.each();
|
||||
|
||||
Reference in New Issue
Block a user