Advertisement
Guest User

Untitled

a guest
Apr 16th, 2013
71
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
  1. The revised approach here is to use a traits class to tell the library when to use heterogenous lookups. This is necessarily formed of both compile-time and run-time components. The primary requirement is that if the traits determine that heterogenous lookup is invalid, then the semantics of homogenous lookup should be preserved as much as possible.
  2.  
  3. The compile-time lookup is necessary not just for performance or simplicity of use, but because some types cannot use the fallback of the existing homogenous find implementation, such as unique_ptr<T> and T*. It is best to ban these at compile-time rather than finding out at run-time that they can't be used.
  4.  
  5. The run-time lookup is necessary because hash types may be stateful so the correct answer to the question "Is heterogenous lookup valid" may depend on the state of the hasher. In this case, it must be legal for the fallback of the existing homogenous find to be used, necessitating that only types which can be implicitly converted to K be permitted.
  6.  
  7. namespace std {
  8. enum class hash_traits_result {
  9. always_true,
  10. always_false,
  11. runtime
  12. };
  13. template<typename T> struct hash_traits {
  14. template<typename A, typename B> struct heterogenous {
  15. static constexpr hash_traits_result result = hash_traits_result::always_false;
  16. };
  17. };
  18. template<> struct hash_traits<std::hash<>> {
  19. template<typename A, typename B> struct heterogenous;
  20. };
  21. template<typename T> struct hash_traits<std::hash<>>::heterogenous<std::unique_ptr<T>, T*> {
  22. static constexpr hash_traits_result result = hash_traits_result::always_true;
  23. };
  24. }
  25. struct mah_hasher {
  26. bool do_the_right_thing;
  27. };
  28. template<> struct hash_traits<mah_hasher>::heterogenous<X, Y> {
  29. static constexpr hash_traits_result result = hash_traits_result::runtime;
  30. bool operator()(const mah_hasher& ref) {
  31. return ref.do_the_right_thing;
  32. }
  33. };
  34.  
  35. template<typename T> iterator find(T&& t);
  36. If hash_traits<F>::heterogenous<K, typename std::decay<T>::type>::result is always_false, remove from overload set.
  37. If it is always_true, continue with heterogenous lookup.
  38. If it is runtime, then static_assert(is_convertible<K, T&&>::result). If hash_traits<F>::heterogenous<K, typename std::decay<T>::type>()(f) is true, continue with heterogenous lookup. Else, return homogenous find(std::forward<T>(t));
  39.  
  40. Mirror for const_iterator version of find, and const/non-const erase. For indexing operator, the selection logic is valid, but in a heterogenous lookup, insertion is impossible, so throw instead if there was no element found.
  41.  
  42. Also included is the hash diamond discussed in the previous version of this paper.
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement