diff --git a/src/lib/functor-util.hpp b/src/lib/functor-util.hpp index b8f4780c3..f10dc7b2b 100644 --- a/src/lib/functor-util.hpp +++ b/src/lib/functor-util.hpp @@ -38,6 +38,7 @@ #define FUNCTOR_UTIL_H_ #include +#include @@ -89,7 +90,7 @@ namespace util { ////////////TODO: refactor namespace. But probably not directly /** convenience shortcut to call two functors in sequence. * @return a Dispatch functor object which incorporates the - * functors as copy and on invocation calls the first + * functors as copy and on invocation calls the first * function and then returns the result of the second */ template Dispatch @@ -102,6 +103,9 @@ namespace util { ////////////TODO: refactor namespace. But probably not directly namespace { // hiding some nasty details... + + using lib::HashVal; + using boost::hash_combine; /** * This Class is used to bypass the access protection @@ -139,6 +143,16 @@ namespace util { ////////////TODO: refactor namespace. But probably not directly && (f1._M_functor._M_unused._M_const_object == f2._M_functor._M_unused._M_const_object ); } // note: we don't cover any member pointer offset + + friend HashVal + hash_value (HijackedFunction const& fun) + { + HashVal hash(0); + hash_combine (hash, fun.invoker_); + hash_combine (hash, fun._M_manager); + hash_combine (hash, fun._M_functor._M_unused._M_const_object); + return hash; // note: member pointer offset part uncovered + } }; } @@ -187,18 +201,41 @@ namespace util { ////////////TODO: refactor namespace. But probably not directly } + /** workaround to calculate a hash value for a given function object. + * @note use with caution. This implementation relies on internal details + * of boost/function; it can be expected to be rather conservative, + * i.e. yielding different hash values for objects, which actually + * are semantically equivalent. + * @warning especially function objects bound to member functions aren't + * fully supported. It \em may happen that we miss differences on the + * offset part and only hash the "this" pointer on some platform. + */ + template + inline HashVal + rawHashValue (function const& fun) + { + typedef HijackedFunction const& Hij; + + return hash_value (reinterpret_cast (fun)); + } + } // namespace util namespace std { namespace tr1 { + /** inject into std::tr1 to be picked up by ADL: + * @return hash value of given functor + * @note use with caution. Hash is calculated + * relying on undocumented boost internals. + */ template - inline size_t + inline lib::HashVal hash_value (function const& fun) { - UNIMPLEMENTED ("hijack the function object and derive some hash value"); + return util::rawHashValue (fun); } - + }} #endif /*UTIL_HPP_*/ diff --git a/tests/lib/functor-util-test.cpp b/tests/lib/functor-util-test.cpp index c031ddc60..8ff8327fb 100644 --- a/tests/lib/functor-util-test.cpp +++ b/tests/lib/functor-util-test.cpp @@ -157,6 +157,7 @@ namespace test { CHECK (h2 == h22); f1 = f2; + h1 = calculateHash (f1); CHECK (h1 == h2); CHECK (h1 != h0);