0

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

  };
}
Keorus
  • 17
  • 4
  • please be more specific than "it didn't work" was there an error? What was that error? – Alan Birtles Nov 08 '22 at 11:05
  • I tried to implement this : typedef multi_index_container,hashed_unique >>> item_list; but mostly I got a message: Invalid use of non-static data member '_items'. This kind of error I can understand it but I did not want to specify it because it is the global implementation that worries me – Keorus Nov 08 '22 at 11:19
  • please [edit] clarifications into the question, the comments don't support enough formatting – Alan Birtles Nov 08 '22 at 12:28
  • i edited too ! :) – Keorus Nov 08 '22 at 12:42
  • Please talk about what goes wrong when you run the code, as well as what you are expecting. More specifically: be as precise as possible for what errors you see. – beep_boop Nov 08 '22 at 18:17

1 Answers1

2

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 
Joaquín M López Muñoz
  • 5,243
  • 1
  • 15
  • 20
  • Hello, thank you for your response ! I would have to share two issues related to two errors after testing the code: "Too few template arguments for class template 'sequenced'" and "No member named 'key' in namespace 'boost::multi_index'clang(no_member)". For the first error, I think that it is necessary to add in argument Tkey ? For the 2nd error having looked at the Boost document, I find nothing about 'key'. 2 Another Question, Why get<1>(); ? i try to find the answer from the Boost Documents but same nothing finds and the .template after _container, i don't find the explication for this. – Keorus Nov 09 '22 at 15:02
  • Please post an additional question including some reasonably complete code snippet showing the problems. – Joaquín M López Muñoz Nov 10 '22 at 10:46
  • Hello ! Sorry my mistake! I made another question below. – Keorus Nov 10 '22 at 11:53