std::unordered_map이 즉시 튜플 키를 사용하여 쉽게 작동할 것으로 기대할 수 있습니다. 그러나 아래와 같이 튜플에 대한 해시 함수를 정의해야 합니다.
template<> struct do_hash<tuple<int, int>> { size_t operator()(std::tuple<int, int> const& tt) const {...} };
이 프로세스는 지루할 수 있으므로 가변 템플릿을 사용하지 않고 C 0x 튜플에 대해 자동화해야 하는 문제로 이어질 수 있습니다.
다음 접근 방식을 사용하면 표준 해시 가능 유형을 포함하는 모든 C 0x 튜플이 unordered_map의 일부가 되고 추가 노력 없이 unordered_set:
#include <tuple> namespace std { namespace { template <class T> inline void hash_combine(std::size_t& seed, T const& v) { // Modified from Boost seed ^= std::hash<T>()(v) + 0x9e3779b9 + (seed << 6) + (seed >> 2); } // Recursive template for hashing tuples template <class Tuple, size_t Index = std::tuple_size<Tuple>::value - 1> struct HashValueImpl { static void apply(size_t& seed, Tuple const& tuple) { HashValueImpl<Tuple, Index - 1>::apply(seed, tuple); hash_combine(seed, std::get<Index>(tuple)); } }; template <class Tuple> struct HashValueImpl<Tuple, 0> { static void apply(size_t& seed, Tuple const& tuple) { hash_combine(seed, std::get<0>(tuple)); } }; } template <typename... TT> struct hash<std::tuple<TT...>> { size_t operator()(std::tuple<TT...> const& tt) const { size_t seed = 0; HashValueImpl<std::tuple<TT...>>::apply(seed, tt); return seed; } }; }
std 네임스페이스에 함수를 배치하면 인수 종속 이름 조회(ADL)를 통해 액세스할 수 있습니다.
std 네임스페이스의 개체를 특수화하는 것은 정의되지 않은 동작입니다. 따라서 표준을 준수하는 솔루션의 경우 코드를 별도의 네임스페이스로 이동하고 ADL의 편리함을 포기하세요.
namespace hash_tuple { // Forward non-tuple types to std::hash template <class TT> struct hash { size_t operator()(TT const& tt) const { return std::hash<TT>()(tt); } }; // Hash function combining values in a tuple template <class Tuple, size_t Index = std::tuple_size<Tuple>::value - 1> struct HashValueImpl { static void apply(size_t& seed, Tuple const& tuple) { HashValueImpl<Tuple, Index - 1>::apply(seed, tuple); hash_combine(seed, std::get<Index>(tuple)); } }; template <class Tuple> struct HashValueImpl<Tuple, 0> { static void apply(size_t& seed, Tuple const& tuple) { hash_combine(seed, std::get<0>(tuple)); } }; // Hash function for tuples template <typename... TT> struct hash<std::tuple<TT...>> { size_t operator()(std::tuple<TT...> const& tt) const { size_t seed = 0; HashValueImpl<std::tuple<TT...>>::apply(seed, tt); return seed; } }; } // namespace hash_tuple
tuple이 아닌 모든 유형을 std로 전달하려면 hash_tuple 네임스페이스 내에서 해시 구현을 선언하세요. :hash std::hash 대신 hash_tuple::hash를 사용하도록 hash_combine을 수정합니다. 나머지 코드는 hash_tuple 네임스페이스 안에 배치합니다.
이 솔루션을 사용하려면 ADL의 편의성을 포기하는 다음 코드를 포함해야 합니다.
unordered_set<tuple<double, int>, hash_tuple::hash<tuple<double, int>>> test2;
위 내용은 사용자 정의 해시 함수를 작성하지 않고 정렬되지 않은 맵에서 튜플을 키로 어떻게 사용할 수 있습니까?의 상세 내용입니다. 자세한 내용은 PHP 중국어 웹사이트의 기타 관련 기사를 참조하세요!