mercredi 28 décembre 2022

Singleton Pattern Template C++

First thing: I m trying to create a Template class at the beginning and its working well. After I wanted to use the singleton design pattern for many reasons, one of the main reason is because i want to try for a project. But I know that this pattern is to be avoided.

Come back to my issue. I show you the code

#include <boost/multi_index_container.hpp>
#include <boost/multi_index/sequenced_index.hpp>
#include <boost/multi_index/hashed_index.hpp>
#include <boost/multi_index/identity.hpp>
#include <boost/multi_index/member.hpp>
#include <boost/config.hpp>
#include <iostream>
#include <stdexcept>

template<typename TK, typename TV>
class MultiContainer{
  
  private:
  
  using value_type = std::pair<TK, TV>;
  
  static MultiContainer<TK, TV>* _singletonCacheServer;
  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::member<value_type,TK,&value_type::first>>>> _container;
  
  MultiContainer(const MultiContainer&) = delete;
  MultiContainer& operator=(const MultiContainer&) = 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:
  
  MultiContainer(int icapacity) : _capacity(icapacity){};
  virtual ~MultiContainer() = default;
  MultiContainer();

  static MultiContainer<TK, TV>* getInstance() {
    if (!_singletonCacheServer) {
        _singletonCacheServer = new MultiContainer;
        return _singletonCacheServer;
    }else{
        delete _singletonCacheServer;
        _singletonCacheServer = nullptr;
    }
  }

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

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

  void remove_key(const TK& key){
    auto& lookup = _container.template get<1>();
    auto it = lookup.find(key);
    if(it != lookup.end()){
      lookup.erase(it);
    }
  }

  void put(const TK& key, const TV& 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<TK, TV>>getItems(){
    return {_container.begin(), _container.end()};
  };

  const TV& get(const TK& 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;
  }
};

int main()
{

  //MultiContainer<std::string, std::string>* a1 = MultiContainer<std::string, std::string>::instance();
  auto cache  = MultiContainer<std::string, std::string>::getInstance();
 
}

The error I got was this: a nonstatic member reference must be relative to a specific object

I tried to declare the function using for the singleton as static to solve the problem but it didn't work too well

I came to ask myself if I could use the singleton with templates, I saw several answers, yes and no so no sure.

I would like to have your opinion on my class so that I can succeed in using it. Because its really something i want to try.

ps: I've also seen posts of people using a different class to implement a singleton and putting in that singleton class, the class we want to turn into a singleton. which gives a kind of class in the middle that makes the connection

Aucun commentaire:

Enregistrer un commentaire