c ++以UUID作为键

时间:2018-04-27 20:01:53

标签: c++ components

所以我有一堆std :: unordered_maps,它们都有一个公共密钥,但数据的数据类型不同。我基本上构建了一个基于组件的实体系统的结构,键是一个包含boost :: uuid的实体类。

添加效果很好,但我正在努力从程序中删除整个实体。我无法找到一种可靠的方法来删除它们而不会影响正在运行的系统(我不想在帧的中间允许删除以避免由于值被删除或用某些默认值替换而导致一帧被闪烁)或者非常慢。

现在我在实体类中有一个bool,程序遍历每个实体并检查它是否设置为true。如果是,则数据点将从地图中删除。

但我对此并不满意。

这是普通实体的样子:

    class Entity{
private:
    boost::uuids::uuid uuid;
    bool protect = false;
    bool status = ENTITY_ALIVE;
public:
    Entity()
    :uuid(boost::uuids::random_generator()()){
    }
    const boost::uuids::uuid &operator ()()const{
        return this->uuid;
    }
    bool operator ==(const Entity &othr)const{
        return this->uuid==othr.uuid;
    }


    void copyComponents(const Entity &source,ComponentBase** mgrs, int c){
        std::cout<<"copying...\n";
        for(int i = 0; i < c; i ++){
            std::cout<<"-";
            mgrs[i]->copyTo(source,*this);
        }
    }
    void kill(){
        if(this->protect==false){
            this->status = ENTITY_DEAD;
        }
    }
    bool getStatus()const{
        return this->status;
    }
    void setProtection(bool status){
        this->protect = status;
    }

    bool getProtection(){
        return this->protect;
    }

    ~Entity(){
//        std::cout<<"ENTITY WAS DELETED!!!!!!!!!!!"<<"\n";
    }
};
struct EntityHasher{
    size_t operator()(const Entity& obj)const{
        return boost::uuids::hash_value((obj)());
    }

};

好的,这就是地图的样子:

typedef typename std::unordered_map<std::reference_wrapper<const Entity>,List<std::shared_ptr<t>>,EntityHasher,std::equal_to<const Entity>> mapType;

该列表是我制作的一个自定义类,它只是将事物存储在双向链表中。没什么好担心的。我这样做是因为访问数据比使用unordered_multi map更容易。

我尝试过:

  • 我试图存储包含地图的类的链接,只是直接将它们删除但没有太大成功。
  • 我试图在访问“死”实体时将其添加到存储无序映射的类中的向量中,然后在名为“removeCorpses”的单独函数中清除。然而,这导致较少使用的组件被遗留的时间太长而且通常只是非常不稳定(可能我在实施它时犯了错误)

请建议我在所有地图中删除实体的一些好方法,将其作为关键字而不会弄乱活动框架等。

1 个答案:

答案 0 :(得分:0)

你可以使用Boost.MultiIndex构建一个类似地图的结构,让尸体首先排列在二级序列索引中,以便在适当的时候删除它们:

<强> Live On Coliru

#include <boost/multi_index_container.hpp>
#include <boost/multi_index/hashed_index.hpp>
#include <boost/multi_index/sequenced_index.hpp>
#include <boost/multi_index/member.hpp>

template<typename Key,typename Value>
struct delayed_erasure_unordered_map_value
{
  Key           first;
  mutable Value second;
};

template<typename Key,typename Value>
using delayed_erasure_unordered_map_base=boost::multi_index_container<
  delayed_erasure_unordered_map_value<Key,Value>,
  boost::multi_index::indexed_by<
    boost::multi_index::hashed_unique<
      boost::multi_index::member<
        delayed_erasure_unordered_map_value<Key,Value>,
        Key,
        &delayed_erasure_unordered_map_value<Key,Value>::first
      >
    >,
    boost::multi_index::sequenced<>
  >
>;

template<typename Key,typename Value>
class delayed_erasure_unordered_map:
  public delayed_erasure_unordered_map_base<Key,Value>
{
  using base=delayed_erasure_unordered_map_base<Key,Value>;
public:
  using iterator=typename base::iterator;

  using base::base;

  void mark_for_erasure(iterator it) // marking same element twice is UB
  {
    auto pit=this->template project<1>(it);
    auto& index=this->template get<1>();
    index.relocate(index.begin(),pit);
    ++num_corpses;
  }

  void erase_marked()
  {
    auto& index=this->template get<1>();
    for(;num_corpses;--num_corpses)index.erase(index.begin());
  }

private:
  std::size_t num_corpses=0;
};

#include <iostream>

int main()
{
  delayed_erasure_unordered_map<int,int> m=
    {{0,0},{1,1},{2,2},{3,3},{4,4},{5,5},{6,6},{7,7},{8,8},{9,9}};

  for(auto it=m.begin(),end=m.end();it!=end;++it){
    if(it->first%2)m.mark_for_erasure(it);
  }
  m.erase_marked();

  for(const auto& x:m){
    std::cout<<"{"<<x.first<<","<<x.second<<"} ";
  }
}

<强>输出

{0,0} {2,2} {4,4} {6,6} {8,8}