简体   繁体   English

如何遍历具有不同类型的多个向量?

[英]how to iterate through several vectors with DIFFERENT types?

Here, I have a custom collection of entities (vectors of different types: Type1 , Type2 , Type3 , Type4 , for simplicity I reduced to two types) with different sizes:在这里,我有一个不同大小的自定义实体集合(不同类型的向量: Type1Type2Type3Type4 ,为简单起见,我简化为两种类型):

#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;
}

My goal is safely iterate over all vectors (entities1, entities2, ...) to run a given external function f_external(Entity e, Args...) :我的目标是安全地遍历所有向量(entities1、entities2、...)以运行给定的外部函数f_external(Entity e, Args...)

for (auto& e : entities1)
    f_external(e, args...) 

for (auto& e : entities2)
    f_external(e, args...) 

or internal function f_internal(Args...) :或内部函数f_internal(Args...)

for (auto& e : entities1)
    e->f_internal(args...) 
    
for (auto& e : entities2)
    e->f_internal(args...) 

Right now, I am writing a lot of code each time:现在,我每次都在写很多代码:

EntityCollection ec;
for (auto& e : ec.getEntity1())
    e->f_internal(args...)
for (auto& e : ec.getEntity2())
    e->f_internal(args...)  

How to automate it in order to minimize the mistakes and changes with adding new Types?如何自动化它以最大程度地减少添加新类型时的错误和更改? I would be grateful if you use C++17 .如果您使用C++17 ,我将不胜感激。

Make your run_function member function take a functor instead of a function pointer:使您的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...);
        // ...
    }

And you can use it with a lambda:您可以将它与 lambda 一起使用:

ec.run_function([&](auto* e) { f_external(e, args...); });
ec.run_function([&](auto* e) { e->f_internal(args...); });

Also consider making template<typename DataType> class AbstractEntity derive from some non-template base so you only need one vector还可以考虑使template<typename DataType> class AbstractEntity从一些非模板基础派生,因此您只需要一个向量

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM