从 std::tuple 个向量中迭代选定的向量
Iterate over selected vectors from a std::tuple of vectors
我正在尝试在 C++11/14 中静态实现实体-组件-系统模式。我已经设法为我的实体制作了一个容器,并且我正在尝试添加功能以处理内部数据。这是我目前的代码:
template<typename... Components>
struct Entity {
std::tuple<Components...> comps;
Entity() = default;
Entity(Components... cs) {
comps = std::make_tuple(cs...);
};
};
template<typename... EntityTypes>
struct EntityCollection {
std::tuple<std::vector<EntityTypes>...> entities;
template<typename EntityType>
void add(EntityType e) {
auto& cont = std::get<std::vector<EntityType>>(entities);
cont.push_back(e);
};
template<typename... Components, typename F>
void for_each_containing(F f) {
// todo... apply f on all entities for which 'Components'
// are a subset of those in the entity.
};
};
我见过使用 boost 融合(以及 stl 适配器)和通用 lambda 循环遍历元组中所有元素的代码,如下所示:
// inside entity class
void update() {
for_each(comps, [](auto& c) { c.update(); }; // assuming all components has an update function
};
但是,我想对包含一组特定组件的所有实体应用一个函数,如 for_each_containing 函数所建议的那样。我一直在尝试使用融合中的 filter_view 写一些东西,但是没有成功...
非常感谢任何帮助!
实用工具:
#include <iostream>
#include <tuple>
#include <vector>
#include <type_traits>
template <typename... Ts>
struct pack {};
template <typename T, typename... Ts>
constexpr bool Contains = false;
template <typename T, typename U, typename... Ts>
constexpr bool Contains<T, U, Ts...> = Contains<T, Ts...>;
template <typename T, typename... Ts>
constexpr bool Contains<T, T, Ts...> = true;
template <bool...>
constexpr bool All = true;
template <bool Head, bool... Tail>
constexpr bool All<Head, Tail...> = Head && All<Tail...>;
template <typename Subset, typename Set>
struct IsSubset;
template <typename... Ts, typename... Us>
struct IsSubset<pack<Ts...>, pack<Us...>>
: std::integral_constant<bool, All<Contains<Ts, Us...>...>> {};
Entity
带有示例 update
成员函数:
template <typename... Components>
struct Entity
{
std::tuple<Components...> comps;
Entity() = default;
Entity(Components... cs)
: comps(cs...)
{
}
void update()
{
std::cout << "Updating " << __PRETTY_FUNCTION__ << std::endl;
}
};
EntityCollection
与 apply
函数:
template <typename... EntityTypes>
struct EntityCollection
{
std::tuple<std::vector<EntityTypes>...> entities;
template <typename EntityType>
void add(EntityType e)
{
auto& cont = std::get<std::vector<EntityType>>(entities);
cont.push_back(e);
}
template <typename... Components, typename F>
void for_each_containing(F f)
{
using expander = int[];
(void)expander{ 0, (void(
apply<Components...>(std::get<std::vector<EntityTypes>>(entities), f)
), 0)... };
}
template <typename... Components, typename... Ts, typename F>
auto apply(std::vector<Entity<Ts...>>& entities, F f)
-> std::enable_if_t<IsSubset<pack<Components...>, pack<Ts...>>{}>
{
for (auto& v : entities)
{
f(v);
}
}
template <typename... Components, typename... Ts, typename F>
auto apply(std::vector<Entity<Ts...>>&, F)
-> std::enable_if_t<!IsSubset<pack<Components...>, pack<Ts...>>{}>
{
}
};
测试:
int main()
{
Entity<int, short> a;
Entity<long, int> b;
Entity<float, double> c;
EntityCollection<Entity<int, short>,
Entity<long, int>,
Entity<float, double>> collection;
collection.add(a);
collection.add(b);
collection.add(c);
collection.for_each_containing<int>([](auto& c){ c.update(); });
collection.for_each_containing<float>([](auto& c){ c.update(); });
collection.for_each_containing<short>([](auto& c){ c.update(); });
collection.for_each_containing<short, int>([](auto& c){ c.update(); });
}
输出:
Updating void Entity<int, short>::update() [Components = <int, short>]
Updating void Entity<long, int>::update() [Components = <long, int>]
Updating void Entity<float, double>::update() [Components = <float, double>]
Updating void Entity<int, short>::update() [Components = <int, short>]
Updating void Entity<int, short>::update() [Components = <int, short>]
我正在尝试在 C++11/14 中静态实现实体-组件-系统模式。我已经设法为我的实体制作了一个容器,并且我正在尝试添加功能以处理内部数据。这是我目前的代码:
template<typename... Components>
struct Entity {
std::tuple<Components...> comps;
Entity() = default;
Entity(Components... cs) {
comps = std::make_tuple(cs...);
};
};
template<typename... EntityTypes>
struct EntityCollection {
std::tuple<std::vector<EntityTypes>...> entities;
template<typename EntityType>
void add(EntityType e) {
auto& cont = std::get<std::vector<EntityType>>(entities);
cont.push_back(e);
};
template<typename... Components, typename F>
void for_each_containing(F f) {
// todo... apply f on all entities for which 'Components'
// are a subset of those in the entity.
};
};
我见过使用 boost 融合(以及 stl 适配器)和通用 lambda 循环遍历元组中所有元素的代码,如下所示:
// inside entity class
void update() {
for_each(comps, [](auto& c) { c.update(); }; // assuming all components has an update function
};
但是,我想对包含一组特定组件的所有实体应用一个函数,如 for_each_containing 函数所建议的那样。我一直在尝试使用融合中的 filter_view 写一些东西,但是没有成功...
非常感谢任何帮助!
实用工具:
#include <iostream>
#include <tuple>
#include <vector>
#include <type_traits>
template <typename... Ts>
struct pack {};
template <typename T, typename... Ts>
constexpr bool Contains = false;
template <typename T, typename U, typename... Ts>
constexpr bool Contains<T, U, Ts...> = Contains<T, Ts...>;
template <typename T, typename... Ts>
constexpr bool Contains<T, T, Ts...> = true;
template <bool...>
constexpr bool All = true;
template <bool Head, bool... Tail>
constexpr bool All<Head, Tail...> = Head && All<Tail...>;
template <typename Subset, typename Set>
struct IsSubset;
template <typename... Ts, typename... Us>
struct IsSubset<pack<Ts...>, pack<Us...>>
: std::integral_constant<bool, All<Contains<Ts, Us...>...>> {};
Entity
带有示例 update
成员函数:
template <typename... Components>
struct Entity
{
std::tuple<Components...> comps;
Entity() = default;
Entity(Components... cs)
: comps(cs...)
{
}
void update()
{
std::cout << "Updating " << __PRETTY_FUNCTION__ << std::endl;
}
};
EntityCollection
与 apply
函数:
template <typename... EntityTypes>
struct EntityCollection
{
std::tuple<std::vector<EntityTypes>...> entities;
template <typename EntityType>
void add(EntityType e)
{
auto& cont = std::get<std::vector<EntityType>>(entities);
cont.push_back(e);
}
template <typename... Components, typename F>
void for_each_containing(F f)
{
using expander = int[];
(void)expander{ 0, (void(
apply<Components...>(std::get<std::vector<EntityTypes>>(entities), f)
), 0)... };
}
template <typename... Components, typename... Ts, typename F>
auto apply(std::vector<Entity<Ts...>>& entities, F f)
-> std::enable_if_t<IsSubset<pack<Components...>, pack<Ts...>>{}>
{
for (auto& v : entities)
{
f(v);
}
}
template <typename... Components, typename... Ts, typename F>
auto apply(std::vector<Entity<Ts...>>&, F)
-> std::enable_if_t<!IsSubset<pack<Components...>, pack<Ts...>>{}>
{
}
};
测试:
int main()
{
Entity<int, short> a;
Entity<long, int> b;
Entity<float, double> c;
EntityCollection<Entity<int, short>,
Entity<long, int>,
Entity<float, double>> collection;
collection.add(a);
collection.add(b);
collection.add(c);
collection.for_each_containing<int>([](auto& c){ c.update(); });
collection.for_each_containing<float>([](auto& c){ c.update(); });
collection.for_each_containing<short>([](auto& c){ c.update(); });
collection.for_each_containing<short, int>([](auto& c){ c.update(); });
}
输出:
Updating void Entity<int, short>::update() [Components = <int, short>]
Updating void Entity<long, int>::update() [Components = <long, int>]
Updating void Entity<float, double>::update() [Components = <float, double>]
Updating void Entity<int, short>::update() [Components = <int, short>]
Updating void Entity<int, short>::update() [Components = <int, short>]