如何遍历多个具有不同类型的向量?
how to iterate through several vectors with DIFFERENT types?
在这里,我有一个自定义的实体集合(不同类型的向量:Type1
、Type2
、Type3
、Type4
,为简单起见,我将其简化为两个类型)不同尺寸:
#include <stdio.h>
#include <vector>
template<typename DataType>
struct AbstractEntity
{
public:
virtual std::vector<DataType>& getParticlesCPU() = 0;
virtual void print() {};
};
// there is one of
// realization of AbstractEntity class
template<typename DataType>
class ClothEntity : public AbstractEntity<DataType>
{
public:
ClothEntity(){
particles.push_back(DataType(1));
particles.push_back(DataType(2));
}
virtual std::vector<DataType>& getParticlesCPU() override {
return particles;
}
virtual void print(){
for (auto& a : particles)
printf("%d\n", a.x);
}
private:
std::vector<DataType> particles;
};
struct Type1{
int x;
Type1(int x_){x = x_;}
};
struct Type2{
int x;
float y;
Type2(int x_){x = x_; y = 0;}
};
class EntityCollection{
using Entity1 = AbstractEntity<Type1>;
using Entity2 = AbstractEntity<Type2>;
public:
EntityCollection(){}
void push_back(Entity1* entity){
entities1.push_back(entity);
}
void push_back(Entity2* entity){
entities2.push_back(entity);
}
std::vector<Entity1*> getEntity1(){
return entities1;
}
std::vector<Entity2*> getEntity2(){
return entities2;
}
private:
template< typename... Ts >
using custom_function_t = void (*) ( Ts... );
template<typename Entity, typename... Ts >
double fun_per_entity( std::vector<Entity>& entities, custom_function_t<Ts...> f, Ts... args ) {
for(auto& entity : entities){
f(entity, args...);
}
}
public:
template<typename... Ts >
void run_function(custom_function_t<Ts...> f, Ts... args){
fun_per_entity(entities1, f, args...);
fun_per_entity(entities2, f, args...);
}
private:
std::vector<Entity1*> entities1;
std::vector<Entity2*> entities2;
};
int main()
{
EntityCollection ec;
ClothEntity<Type1> e1;
ClothEntity<Type2> e2;
ec.push_back(&e1);
ec.push_back(&e2);
// ec.run_function(print); // does not work
for (auto& ev: ec.getEntity1())
ev->print();
for (auto& ev: ec.getEntity2())
ev->print();
return 0;
}
我的目标是安全地遍历所有向量(实体 1、实体 2、...)到 运行 给定的外部函数 f_external(Entity e, Args...)
:
for (auto& e : entities1)
f_external(e, args...)
for (auto& e : entities2)
f_external(e, args...)
或内部函数f_internal(Args...)
:
for (auto& e : entities1)
e->f_internal(args...)
for (auto& e : entities2)
e->f_internal(args...)
现在,我每次都在写很多代码:
EntityCollection ec;
for (auto& e : ec.getEntity1())
e->f_internal(args...)
for (auto& e : ec.getEntity2())
e->f_internal(args...)
如何使其自动化以最大程度地减少错误和添加新类型的变化?如果您使用 C++17
.
将不胜感激
使您的 run_function
成员函数采用仿函数而不是函数指针:
template<typename Entity, typename F, typename... Ts>
static void fun_per_entity(std::vector<Entity*>& entities, F&& f, Ts&&... args) {
for (auto& entity : entities) {
f(entity, args...);
}
}
public:
template<typename F, typename... Ts>
void run_function(F&& f, Ts&&... args) {
fun_per_entity(entities1, f, args...);
fun_per_entity(entities2, f, args...);
fun_per_entity(entities3, f, args...);
// ...
}
您可以将它与 lambda 一起使用:
ec.run_function([&](auto* e) { f_external(e, args...); });
ec.run_function([&](auto* e) { e->f_internal(args...); });
还可以考虑使 template<typename DataType> class AbstractEntity
从某些 non-template 基派生,这样您只需要一个向量
在这里,我有一个自定义的实体集合(不同类型的向量:Type1
、Type2
、Type3
、Type4
,为简单起见,我将其简化为两个类型)不同尺寸:
#include <stdio.h>
#include <vector>
template<typename DataType>
struct AbstractEntity
{
public:
virtual std::vector<DataType>& getParticlesCPU() = 0;
virtual void print() {};
};
// there is one of
// realization of AbstractEntity class
template<typename DataType>
class ClothEntity : public AbstractEntity<DataType>
{
public:
ClothEntity(){
particles.push_back(DataType(1));
particles.push_back(DataType(2));
}
virtual std::vector<DataType>& getParticlesCPU() override {
return particles;
}
virtual void print(){
for (auto& a : particles)
printf("%d\n", a.x);
}
private:
std::vector<DataType> particles;
};
struct Type1{
int x;
Type1(int x_){x = x_;}
};
struct Type2{
int x;
float y;
Type2(int x_){x = x_; y = 0;}
};
class EntityCollection{
using Entity1 = AbstractEntity<Type1>;
using Entity2 = AbstractEntity<Type2>;
public:
EntityCollection(){}
void push_back(Entity1* entity){
entities1.push_back(entity);
}
void push_back(Entity2* entity){
entities2.push_back(entity);
}
std::vector<Entity1*> getEntity1(){
return entities1;
}
std::vector<Entity2*> getEntity2(){
return entities2;
}
private:
template< typename... Ts >
using custom_function_t = void (*) ( Ts... );
template<typename Entity, typename... Ts >
double fun_per_entity( std::vector<Entity>& entities, custom_function_t<Ts...> f, Ts... args ) {
for(auto& entity : entities){
f(entity, args...);
}
}
public:
template<typename... Ts >
void run_function(custom_function_t<Ts...> f, Ts... args){
fun_per_entity(entities1, f, args...);
fun_per_entity(entities2, f, args...);
}
private:
std::vector<Entity1*> entities1;
std::vector<Entity2*> entities2;
};
int main()
{
EntityCollection ec;
ClothEntity<Type1> e1;
ClothEntity<Type2> e2;
ec.push_back(&e1);
ec.push_back(&e2);
// ec.run_function(print); // does not work
for (auto& ev: ec.getEntity1())
ev->print();
for (auto& ev: ec.getEntity2())
ev->print();
return 0;
}
我的目标是安全地遍历所有向量(实体 1、实体 2、...)到 运行 给定的外部函数 f_external(Entity e, Args...)
:
for (auto& e : entities1)
f_external(e, args...)
for (auto& e : entities2)
f_external(e, args...)
或内部函数f_internal(Args...)
:
for (auto& e : entities1)
e->f_internal(args...)
for (auto& e : entities2)
e->f_internal(args...)
现在,我每次都在写很多代码:
EntityCollection ec;
for (auto& e : ec.getEntity1())
e->f_internal(args...)
for (auto& e : ec.getEntity2())
e->f_internal(args...)
如何使其自动化以最大程度地减少错误和添加新类型的变化?如果您使用 C++17
.
使您的 run_function
成员函数采用仿函数而不是函数指针:
template<typename Entity, typename F, typename... Ts>
static void fun_per_entity(std::vector<Entity*>& entities, F&& f, Ts&&... args) {
for (auto& entity : entities) {
f(entity, args...);
}
}
public:
template<typename F, typename... Ts>
void run_function(F&& f, Ts&&... args) {
fun_per_entity(entities1, f, args...);
fun_per_entity(entities2, f, args...);
fun_per_entity(entities3, f, args...);
// ...
}
您可以将它与 lambda 一起使用:
ec.run_function([&](auto* e) { f_external(e, args...); });
ec.run_function([&](auto* e) { e->f_internal(args...); });
还可以考虑使 template<typename DataType> class AbstractEntity
从某些 non-template 基派生,这样您只需要一个向量