Keorus
Keorus

Reputation: 9

c++ serialization

Currently my class looks like this, by unit tests done, it works but my goal will be to implement as precise in question the lib Boost and especially the multi index container.

I tried to change the type of the items but it didn't work, like this:

typedef multi_index_container<items,indexed_by<sequenced<>,hashed_unique<identity<Item> >>> item_list;

I got a message: Invalid use of non-static data member '_items'. This kind of error I can understand it but i not specify it because it is the global implementation that worries me

If you find any other error apart from my precise question, I am also a taker.

 template<typename Tkey, typename Tval>
 class CacheWeb{

  private:
   unsigned int capacity;
   std::list<std::pair<Tkey, Tval>> items;
   std::unordered_map<key, typename std::list<std::pair<Tkey, Tval>>::iterator> lookup;

   CacheWeb(const CacheWeb&) = delete;
   CacheWeb& operator=(const CacheWeb&) = delete;

   int capacityOut(){
      if( capacity == 0 || lookup.size() < capacity ) {
        return 0;
      }
      int cnt = 0;
      while(lookup.size() > capacity) {
        lookup.erase(items.back().first);
        items.pop_back();
        ++cnt;
      }
      return cnt;      
   };

  public:
   CacheWeb(int icapacity) : capacity(icapacity){};
   virtual ~CacheWeb() = default;
   

    int size(){
      return lookup.size();
    };
    bool empty(){
    return lookup.empty(); 
    };
    void clear(){
      lookup.clear(); 
      items.clear();
    };

    bool contains(const Tkey& key){
      return lookup.find(key) != lookup.end(); 
    };

    void remove(const Tkey& key){
      auto it = lookup.find(key);
      items.erase(it->second);
      lookup.erase(it); 
    };

    void put(const Tkey& key, const Tval& val){
      auto it = lookup.find(key);
      if( it != lookup.end() ) {
        it->second->second = val;
        items.splice(items.begin(), items, it->second);
        return;
      }
      items.emplace_front(key, val);
      lookup[key] = items.begin();
      capacityOut();
    };

    std::list<std::pair<Tkey, Tval>>getItems(){
      return items;
    };

    const VAL_T& get(const Tkey& key){
    
      const auto it = lookup.find(key);
      if( it == lookup.end() ) {
        throw std::invalid_argument("Key does not exist");
      }
      items.splice(items.begin(), items, it->second);
      return it->second->second;
    };

  };
}

Upvotes: 0

Views: 168

Answers (1)

Something like this can do:

Live Coliru Demo

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

template<typename Tkey, typename Tval>
class CacheWeb{
  private:
  using value_type = std::pair<Tkey, Tval>;
  
  unsigned int capacity;
  boost::multi_index_container<
    value_type,
    boost::multi_index::indexed_by<
      boost::multi_index::sequenced<>,
      boost::multi_index::hashed_unique<boost::multi_index::key<&value_type::first>>
    >
  > container; 
  
  CacheWeb(const CacheWeb&) = delete;
  CacheWeb& operator=(const CacheWeb&) = delete;

  int capacityOut(){
      if( capacity == 0 || container.size() < capacity ) {
        return 0;
      }
      int cnt = 0;
      while(container.size() > capacity) {
        container.pop_back();
        ++cnt;
      }
      return cnt;      
  };

  public:
  CacheWeb(int icapacity) : capacity(icapacity){};
  virtual ~CacheWeb() = default;
   

  int size(){
    return container.size();
  };
  bool empty(){
    return container.empty(); 
  };
  void clear(){
    container.clear(); 
  };

  bool contains(const Tkey& key){
    const auto& lookup = container.template get<1>();
    return lookup.find(key) != container.template get<1>().end(); 
  };

  void remove(const Tkey& key){
    container.erase(key);
  };

  void put(const Tkey& key, const Tval& val){
    auto& lookup = container.template get<1>();
    auto it = lookup.find(key);
    if( it != lookup.end() ) {
      lookup.modify(it,[&](value_type& x){ x.second = val; });
    }
    else{
      it=lookup.emplace(key, val).first;
    }
    container.relocate(container.begin(),container.template project<0>(it));
    capacityOut();
  };

  std::list<std::pair<Tkey, Tval>>getItems(){
    return {container.begin(), container.end()};
  };

  const Tval& get(const Tkey& key){
    const auto& lookup = container.template get<1>();
    const auto it = lookup.find(key);
    if( it == lookup.end() ) {
      throw std::invalid_argument("Key does not exist");
    }
    return it->second;
  }
};
  
#include <iostream>

int main()
{
  CacheWeb<int,int> c(10);
  for(int i=0;i<11;++i)c.put(i,i);
  
  for(const auto& x:c.getItems()){
    std::cout<<"("<<x.first<<","<<x.second<<")";
  }
  std::cout<<"\n";
  
  for(int i=1;i<11;++i){
    std::cout<<i<<"->"<<c.get(i)<<" ";
  }
  std::cout<<"\n";
}

Output

(10,10)(9,9)(8,8)(7,7)(6,6)(5,5)(4,4)(3,3)(2,2)(1,1)
1->1 2->2 3->3 4->4 5->5 6->6 7->7 8->8 9->9 10->10 

Upvotes: 2

Related Questions