#pragma once #include #include namespace torch { // NOTE: hash_combine is based on implementation from Boost // // Boost Software License - Version 1.0 - August 17th, 2003 // // Permission is hereby granted, free of charge, to any person or organization // obtaining a copy of the software and accompanying documentation covered by // this license (the "Software") to use, reproduce, display, distribute, // execute, and transmit the Software, and to prepare derivative works of the // Software, and to permit third-parties to whom the Software is furnished to // do so, all subject to the following: // // The copyright notices in the Software and this entire statement, including // the above license grant, this restriction and the following disclaimer, // must be included in all copies of the Software, in whole or in part, and // all derivative works of the Software, unless such copies or derivative // works are solely in the form of machine-executable object code generated by // a source language processor. // // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, // FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT // SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE // FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE, // ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER // DEALINGS IN THE SOFTWARE. inline size_t hash_combine(size_t seed, size_t value) { return seed ^ (value + 0x9e3779b9 + (seed << 6u) + (seed >> 2u)); } //////////////////////////////////////////////////////////////////////////////// // torch::hash implementation //////////////////////////////////////////////////////////////////////////////// namespace _hash_detail { // Use template argument deduction to shorten calls to torch::hash template size_t simple_get_hash(const T& o); template using type_if_not_enum = typename std::enable_if::value, V>::type; // Use SFINAE to dispatch to std::hash if possible, cast enum types to int automatically, // and fall back to T::hash otherwise. // NOTE: C++14 added support for hashing enum types to the standard, and some compilers // implement it even when C++14 flags aren't specified. This is why we have to disable // this overload if T is an enum type (and use the one below in this case). template auto dispatch_hash(const T& o) -> decltype(std::hash()(o), type_if_not_enum()) { return std::hash()(o); } template typename std::enable_if::value, size_t>::type dispatch_hash(const T& o) { using R = typename std::underlying_type::type; return std::hash()(static_cast(o)); } template auto dispatch_hash(const T& o) -> decltype(T::hash(o), size_t()) { return T::hash(o); } } // namespace _hash_detail // Hasher struct template struct hash { size_t operator()(const T& o) const { return _hash_detail::dispatch_hash(o); }; }; // Specialization for std::tuple template struct hash> { template struct tuple_hash { size_t operator()(const std::tuple& t) const { return hash_combine(_hash_detail::simple_get_hash(std::get(t)), tuple_hash()(t)); } }; template struct tuple_hash<0, Ts...> { size_t operator()(const std::tuple& t) const { return _hash_detail::simple_get_hash(std::get<0>(t)); } }; size_t operator()(const std::tuple& t) const { return tuple_hash()(t); } }; // Specialization for std::vector template struct hash> { size_t operator()(const std::vector& v) const { size_t seed = 0; for (const auto & elem : v) { seed = hash_combine(seed, _hash_detail::simple_get_hash(elem)); } return seed; } }; namespace _hash_detail { template size_t simple_get_hash(const T& o) { return torch::hash()(o); } } // namespace _hash_detail // Use this function to actually hash multiple things in one line. // Dispatches to torch::hash, so it can hash containers. // Example: // // static size_t hash(const MyStruct& s) { // return get_hash(s.member1, s.member2, s.member3); // } template size_t get_hash(const Types&... args) { return torch::hash()(std::tie(args...)); } } // namespace torch