I have a hash process implemented using the Howard Hinnant method (shared hash_append overload hash_append ).
The purpose of this method is to create a class hash for the βmemoizeβ result of the computation (see the end of this answer), so I ran into some problem. In particular, consider the following possible Input class, which should be hashed:
struct A { virtual int do_stuff() const = 0; virtual ~A(); }; struct B: A { int do_stuff() const override { return 0; } }; struct C: A { const int u; int do_stuff() const override { return u; } }; struct Input { A const& a;
Now, if I want hash Input , I will have something like:
template <class HashAlgorithm> void hash_append(HashAlgorithm& h, Input const& input) { hash_append(h, typeid(input)); hash_append(h, typeid(input.a)); }
I need hash_append overload for A :
template <class HashAlgorithm> void hash_append(HashAlgorithm& h, A const& a) { hash_append(h, typeid(a)); }
The problem is that depending on the type of runtime A I will need to add additional information to the hash file, for example. for C I need to add u .
I thought of the following solutions (and disadvantages):
add a virtual method to A , which returns a specific value that can be added to the typeid() hash, but:
- This means adding a method inside
A that is not related to the purpose of A , so I don't really like this idea (in particular, because I have several classes of A ); - this violates the concept of
hash_append , since the method will have a unique return type for all inheriting classes.
Make a bunch of dynamic_cast inside hash_append :
- I found this pretty ugly ... in particular, if I have several classes similar to
A ; - this is error prone: if someone adds new children to
A and does not add dynamic_cast inside hash_append .
Is there a way to hash a polymorphic type without having to change the type itself or rely on the dynamic_cast bunch?
The ultimate goal is to be able to remember the results of some heavy functions. We describe the basic structure of my application:
struct Input { }; struct Result { }; Result solve(Input const&);
The solve function is computationally heavy, so I want to save the results of previous calculations in a file using the Input s hash, for example. something like:
// depends on hash_append std::string hash(Input const&); Result load_or_solve(Input const& input) { auto h = hash(input); Result result; if (exists(h)) { // if result exists, load it result = load(h); } else { // otherwize, solve + store result = solve(input); store(h, result); } return result; }
The load and store methods will load and store the results from files, the goal is to memoize the solutions between different runs.
If you have a suggestion on how to save these results without having to discuss the above issues, I will be happy to read them.