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

  };
}
5
  • please be more specific than "it didn't work" was there an error? What was that error? Commented Nov 8, 2022 at 11:05
  • I tried to implement this : typedef multi_index_container<items,indexed_by<sequenced<>,hashed_unique<identity<Item> >>> 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 Commented Nov 8, 2022 at 11:19
  • please edit clarifications into the question, the comments don't support enough formatting Commented Nov 8, 2022 at 12:28
  • i edited too ! :) Commented Nov 8, 2022 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. Commented Nov 8, 2022 at 18:17

1 Answer 1

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 
Sign up to request clarification or add additional context in comments.

3 Comments

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.
Please post an additional question including some reasonably complete code snippet showing the problems.
Hello ! Sorry my mistake! I made another question below.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.