#ifndef CACHABLE_H #define CACHABLE_H #include #include #include #include #include namespace cachable { template void hashcomb(std::size_t &x, T &&v) { x ^= std::hash::type>::type>()(v) + 0x9e3779b9 + (x<<6) + (x>>2); } template struct tuplehashfnreal { static void call(std::size_t &x, const std::tuple &p) { tuplehashfnreal::call(x,p); hashcomb(x,std::get(p)); } }; template struct tuplehashfnreal<0,T...> { static void call(std::size_t &x, const std::tuple &p) { } }; template struct tuplehash : public std::unary_function,std::size_t> { std::size_t operator()(const std::tuple &p) const { std::size_t ret = 0; tuplehashfnreal>::value, T...>::call(ret,p); return ret; } }; template class memocache { public: typedef std::tuple InT; template const RetT *find(T &&...p) const { static_assert(sizeof...(T) == sizeof...(Params), "cachable::memocache::find called with wrong parameters"); auto loc = cache.find(std::forward_as_tuple(p...)); if (loc==cache.end()) return nullptr; return &(loc->second); } template RetT &add(RT &&out, T &&...in) { static_assert(sizeof...(T) == sizeof...(Params), "cachable::memocache::add called with wrong parameters"); return cache[std::forward_as_tuple(in...)] = out; } private: std::unordered_map> cache; //std::map cache; }; namespace inner { template inline std::function _cachable(F &fn, RT (F::*)(PT...) const) { return [fn](PT ...params)->RT { static memocache _cache; auto loc = _cache.find(params...); if (loc==nullptr) return _cache.add(fn(params...),params...); else return *loc; }; } } template inline auto cachable(F fn) -> decltype(inner::_cachable(fn,&F::operator())) { return inner::_cachable(fn,&F::operator()); } } // end cachable namespace #endif