{"action":"created","issue":{"url":"https://api.github.com/repos/akrzemi1/compact_optional/issues/1","labels_url":"https://api.github.com/repos/akrzemi1/compact_optional/issues/1/labels{/name}","comments_url":"https://api.github.com/repos/akrzemi1/compact_optional/issues/1/comments","events_url":"https://api.github.com/repos/akrzemi1/compact_optional/issues/1/events","html_url":"https://github.com/akrzemi1/compact_optional/issues/1","id":104058316,"number":1,"title":"Efficient `std::hash` implementation","user":{"login":"gnzlbg","id":904614,"avatar_url":"https://avatars.githubusercontent.com/u/904614?v=3","gravatar_id":"","url":"https://api.github.com/users/gnzlbg","html_url":"https://github.com/gnzlbg","followers_url":"https://api.github.com/users/gnzlbg/followers","following_url":"https://api.github.com/users/gnzlbg/following{/other_user}","gists_url":"https://api.github.com/users/gnzlbg/gists{/gist_id}","starred_url":"https://api.github.com/users/gnzlbg/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/gnzlbg/subscriptions","organizations_url":"https://api.github.com/users/gnzlbg/orgs","repos_url":"https://api.github.com/users/gnzlbg/repos","events_url":"https://api.github.com/users/gnzlbg/events{/privacy}","received_events_url":"https://api.github.com/users/gnzlbg/received_events","type":"User","site_admin":false},"labels":[],"state":"open","locked":false,"assignee":null,"milestone":null,"comments":1,"created_at":"2015-08-31T13:56:23Z","updated_at":"2015-08-31T14:22:15Z","closed_at":null,"body":"How can I efficiently implement std::hash for `compact_optional`?\r\n\r\nMy first attempt was:\r\n\r\n```c++\r\ntemplate<typename N, typename Tag>\r\nstruct hash<compact_optional<N, Tag>> {\r\n  using Key = compact_optional<N, Tag>;\r\n  using result_type = size_t;\r\n  using value_type = typename N::value_type;\r\n  size_t operator()(Key const& k) const noexcept {\r\n    return k? std::hash<value_type>(*k) : std::hash<value_type>(my_sentinel);\r\n  }\r\n};\r\n```\r\n\r\nFor integers this it introduces an extra branch. Basically in this case I want to get the value even if the optional is empty. Is there a way to do this through the optional interface?  The only solution that came to mind is to rely on the C representation (and thus the implementation details of optional): \r\n\r\n```c++\r\ntemplate<typename N, typename Tag>\r\nstruct hash<compact_optional<N, Tag>> {\r\n  using Key = compact_optional<N, Tag>;\r\n  using result_type = size_t;\r\n  using value_type = typename N::value_type;\r\n  size_t operator()(Key const& k) const noexcept {\r\n    // don't do this at home:\r\n    return std::hash<value_type>(reinterpret_cast<value_type const&>(k));\r\n  }\r\n};\r\n```\r\n\r\nIs there a way to have the cake and eat it too without having to rely on implementation details of compact optional? \r\n\r\nIn particular I would like to exploit the fact that for integers the sentinel value is just another hashable value to eliminate the branch. For other types like strings I am not sure if this could also be done. "},"comment":{"url":"https://api.github.com/repos/akrzemi1/compact_optional/issues/comments/136385128","html_url":"https://github.com/akrzemi1/compact_optional/issues/1#issuecomment-136385128","issue_url":"https://api.github.com/repos/akrzemi1/compact_optional/issues/1","id":136385128,"user":{"login":"akrzemi1","id":2912717,"avatar_url":"https://avatars.githubusercontent.com/u/2912717?v=3","gravatar_id":"","url":"https://api.github.com/users/akrzemi1","html_url":"https://github.com/akrzemi1","followers_url":"https://api.github.com/users/akrzemi1/followers","following_url":"https://api.github.com/users/akrzemi1/following{/other_user}","gists_url":"https://api.github.com/users/akrzemi1/gists{/gist_id}","starred_url":"https://api.github.com/users/akrzemi1/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/akrzemi1/subscriptions","organizations_url":"https://api.github.com/users/akrzemi1/orgs","repos_url":"https://api.github.com/users/akrzemi1/repos","events_url":"https://api.github.com/users/akrzemi1/events{/privacy}","received_events_url":"https://api.github.com/users/akrzemi1/received_events","type":"User","site_admin":false},"created_at":"2015-08-31T14:22:15Z","updated_at":"2015-08-31T14:22:15Z","body":"Thanks for bringing this issue up.\r\n\r\nI can in fact see two issues involved here: \r\n1. Access the sentinel value in a \"portable\" way, that is the way guaranteed to work by the framework.\r\n2. Cheaply get the underlying value (for performance reasons).\r\n\r\nThe (1) is already there. The library is not documented decently, so it might not be visible at first, but the policies need to adhere to the stable syntactic interface, so you can rely on that:\r\n\r\n```cpp\r\ntemplate <typename Policy, typename Tag>\r\nstruct hash<compact_optional<Policy, Tag>>\r\n{\r\n  using Key = compact_optional<Policy, Tag>;\r\n  using RawType = typename Key::value_type;\r\n\r\n  size_t operator()(Key const& k) const noexcept\r\n  {\r\n    std::hash<RawType> h;\r\n    return h(k.has_value() ? k.value() : Policy::empty_value());\r\n  }\r\n};\r\n```\r\n\r\nThe second requirement is not achievable today. This is a good motivation for giving unsafe but fast access to the internal representation."}}