A library for working with phylogenetic and population genetic data.
v0.32.0
hash_tuple.hpp
Go to the documentation of this file.
1 #ifndef GENESIS_UTILS_CONTAINERS_HASH_TUPLE_H_
2 #define GENESIS_UTILS_CONTAINERS_HASH_TUPLE_H_
3 
4 /*
5  Genesis - A toolkit for working with phylogenetic data.
6  Copyright (C) 2014-2020 Lucas Czech
7 
8  This program is free software: you can redistribute it and/or modify
9  it under the terms of the GNU General Public License as published by
10  the Free Software Foundation, either version 3 of the License, or
11  (at your option) any later version.
12 
13  This program is distributed in the hope that it will be useful,
14  but WITHOUT ANY WARRANTY; without even the implied warranty of
15  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16  GNU General Public License for more details.
17 
18  You should have received a copy of the GNU General Public License
19  along with this program. If not, see <http://www.gnu.org/licenses/>.
20 
21  Contact:
22  Lucas Czech <lucas.czech@h-its.org>
23  Exelixis Lab, Heidelberg Institute for Theoretical Studies
24  Schloss-Wolfsbrunnenweg 35, D-69118 Heidelberg, Germany
25 */
26 
35 
36 #include <tuple>
37 
38 namespace genesis {
39 namespace utils {
40 
41 // =================================================================================================
42 // Helper For Hashing Tuples
43 // =================================================================================================
44 
45 // These helper functions and structs allow for each std::tuple that consists of hashable types
46 // to be hashed automatically as well.
47 //
48 // Code adapted from https://stackoverflow.com/a/7115547/4184258 and
49 // https://blog.adamfurmanek.pl/2019/09/28/caching-result-of-any-function-in-c/
50 // We replaced their hash_combine by our 64bit implementation.
51 
52 namespace
53 {
54  // Recursive template code derived from Matthieu M.
55  template <class Tuple, size_t Index = std::tuple_size<Tuple>::value - 1>
56  struct HashValueImpl
57  {
58  static void apply( size_t& seed, Tuple const& tuple )
59  {
60  HashValueImpl<Tuple, Index-1>::apply(seed, tuple);
61  seed = hash_combine( seed, std::get<Index>( tuple ));
62  }
63  };
64 
65  template <class Tuple>
66  struct HashValueImpl<Tuple,0>
67  {
68  static void apply( size_t& seed, Tuple const& tuple )
69  {
70  seed = hash_combine( seed, std::get<0>( tuple ));
71  }
72  };
73 }
74 
75 template <typename TT>
76 struct hash
77 {
78  size_t operator()( TT const& tt ) const
79  {
80  return std::hash<TT>()(tt);
81  }
82 };
83 
84 template <typename ... TT>
85 struct hash<std::tuple<TT...>>
86 {
87  size_t operator()(std::tuple<TT...> const& tt) const
88  {
89  size_t seed = 0;
90  HashValueImpl<std::tuple<TT...> >::apply( seed, tt );
91  return seed;
92  }
93 };
94 
95 
96 } // namespace utils
97 } // namespace genesis
98 
99 #endif // include guard
genesis::utils::hash< std::tuple< TT... > >::operator()
size_t operator()(std::tuple< TT... > const &tt) const
Definition: hash_tuple.hpp:87
std.hpp
Provides some valuable additions to STD.
genesis::utils::hash
Definition: hash_tuple.hpp:76
genesis::utils::hash::operator()
size_t operator()(TT const &tt) const
Definition: hash_tuple.hpp:78
genesis
Container namespace for all symbols of genesis in order to keep them separate when used as a library.
Definition: placement/formats/edge_color.cpp:42
genesis::utils::hash_combine
constexpr std::size_t hash_combine(std::size_t seed, T const &value)
Combine a seed value (e.g., another hash) with the hash of a given type.
Definition: std.hpp:160