Дело в том, что ваш Cache
не адресован самим кэшированным объектом, иначе это будет бесполезно.
Идея Cache
состоит в том, чтобы избежать некоторых вычислений, поэтому индексом будут параметры вычисления, которые будут напрямую отображаться на результат, если он уже существует.
Теперь вам может понадобиться второй индекс для удаления объектов из кэша, но это не обязательно. Конечно, есть и другие доступные стратегии.
Если вы действительно хотите удалить объекты из кэша, как только они не используются где-либо еще в приложении, тогда, фактически, вы можете использовать вторичный индекс. Идея здесь, однако, заключается в том, чтобы индексировать в соответствии с T*
, а не weak_ptr<T>
, а сохранить weak_ptr<T>
, потому что в противном случае вы не можете создать новый shared_ptr
с тем же счетчиком ссылок.
Точная структура зависит от того, трудно ли пересчитать параметры вычисления после того факта, если это так, простое решение:
template <typename K, typename V>
class Cache: boost::enable_shared_from_this<Cache>
{
typedef std::map<K, boost::weak_ptr<V>> KeyValueMap;
typedef std::map<V*, KeyValueMap::iterator> DeleterMap;
struct Deleter {
Deleter(boost::weak_ptr<Cache> c): _cache(c) {}
void operator()(V* v) {
boost::shared_ptr<Cache> cache = _cache.lock();
if (cache.get() == 0) { delete v; return; }
DeleterMap::iterator it = _cache.delmap.find(v);
_cache.key2val.erase(it->second);
_delmap.erase(it);
delete v;
}
boost::weak_ptr<Cache> _cache;
}; // Deleter
public:
size_t size() const { return _key2val.size(); }
boost::shared_ptr<V> get(K const& k) const {
KeyValueMap::const_iterator it = _key2val.find(k);
if (it != _key2val.end()) { return boost::shared_ptr<V>(it->second); }
// need to create it
boost::shared_ptr<V> ptr(new_value(k),
Deleter(boost::shared_from_this()));
KeyValueMap::iterator kv = _key2val.insert(std::make_pair(k, ptr)).first;
_delmap.insert(std::make_pair(ptr.get(), kv));
return ptr;
}
private:
mutable KeyValueMap _key2val;
mutable DeleterMap _delmap;
};
Обратите внимание на особую сложность: указатель может пережить Cache
, поэтому нам нужен какой-то трюк здесь ...
И к вашему сведению, хотя это кажется возможным, я совсем не уверен в этом коде: непроверенный, недоказанный, бла, бла;)