I had an idea for a general cache, based on the idea that caches are
essentially trying to avoid re-calling expensive functions with the
same parameters as last time. So typically you build a cache key from
the params, put it in a map, etc. But what if we did things slightly
differently...
template <typename T>
struct cache
{
typedef boost::function< T () > retriever_function;
typedef std::map
Gottlob Frege wrote:
I had an idea for a general cache, based on the idea that caches are essentially trying to avoid re-calling expensive functions with the same parameters as last time. So typically you build a cache key from the params, put it in a map, etc. But what if we did things slightly differently...
template <typename T> struct cache { typedef boost::function< T () > retriever_function;
typedef std::map
map; map m; T retrieve(retriever_function retriever) { map::iterator it = m.find(retriever); if (it != m.end()) { return it->second; } else { T t = retriever(); m[retriever] = t; return t; } } };
Basically, instead of building a key from the params, build a key from the params + the function that takes the params. Then, as a bonus, you don't need to worry about packing/unpacking the params - just let bind() do that for you! The other bonus is that you can cache things that may be created via different methonds.
So what's the problem?
The problem is that boost::function and boost::bind don't have operator<(), so you can't put a boost::function in a map. :-(
(actually it appears boost::bind does have an operator<, but it doesn't do what I want - it actually bind's the operator< into a function!)
Any advice? Any chance boost::function might gain a < operator? (One that compared the underlying function and the params, possibly handled different numbe of params, etc - although I could live with requiring all the param types to be the same. ie basically boost::function would pass most of the work off to the function object (ie bind))
I'm not 100% sure what you're trying to do, but std::map and std::set take a type parameter that defined an ordering. For example: std::set< int, std::greater<int> > This means that you can specialise std::less for the Boost classes, or write your own separate comparator (they're functors) and specify that in the map type. Maybe something along these lines (I've probably got the syntax wrong for the specialisation): template<> std::less< boost::function > : public std::binary_function < boost::function, boost::function, bool > { bool operator()( const boost::function &left, const boost::function &right ) { return ...; } }; K
On 3/16/07, Gottlob Frege
I had an idea for a general cache, based on the idea that caches are essentially trying to avoid re-calling expensive functions with the same parameters as last time. So typically you build a cache key from the params, put it in a map, etc. But what if we did things slightly differently...
<snip>
Basically, instead of building a key from the params, build a key from the params + the function that takes the params. Then, as a bonus, you don't need to worry about packing/unpacking the params - just let bind() do that for you! The other bonus is that you can cache things that may be created via different methonds.
So what's the problem?
Other than what you specify, it sounds like the memory overhead on that will be very high, something you don't exactly want in a cache. I think a generic cache that could use anything from functions to strings to integers as keys would be preferable.
- Tony
-- Cory Nelson http://www.int64.org
participants (3)
-
Cory Nelson
-
Gottlob Frege
-
Kirit Sælensminde