BDE 4.14.0 Production release
Loading...
Searching...
No Matches
bslh_hashtuple.h
Go to the documentation of this file.
1/// @file bslh_hashtuple.h
2///
3/// The content of this file has been pre-processed for Doxygen.
4///
5
6
7// bslh_hashtuple.h -*-C++-*-
8#ifndef INCLUDED_BSLH_HASHTUPLE
9#define INCLUDED_BSLH_HASHTUPLE
10
11#include <bsls_ident.h>
12BSLS_IDENT("$Id: $")
13
14/// @defgroup bslh_hashtuple bslh_hashtuple
15/// @brief Provide `hashAppend` for `std::tuple`.
16/// @addtogroup bsl
17/// @{
18/// @addtogroup bslh
19/// @{
20/// @addtogroup bslh_hashtuple
21/// @{
22///
23/// <h1> Outline </h1>
24/// * <a href="#bslh_hashtuple-purpose"> Purpose</a>
25/// * <a href="#bslh_hashtuple-description"> Description </a>
26/// * <a href="#bslh_hashtuple-usage"> Usage </a>
27/// * <a href="#bslh_hashtuple-example-1-hashing-a-tuple-of-integer-values"> Example 1: Hashing a Tuple of Integer Values </a>
28///
29/// # Purpose {#bslh_hashtuple-purpose}
30/// Provide `hashAppend` for `std::tuple`.
31///
32/// # Description {#bslh_hashtuple-description}
33/// This component provides a free function template,
34/// `bslh::hashAppend`, overloaded for the `std::tuple` class template.
35/// Including this function allows for `std::tuple` types (and types that
36/// contain them) to be used as keys in BDE hashed containers.
37///
38/// Note that use of this component requires that the language standard be 2011
39/// or later, as that is when `std::tuple` first appears.
40///
41/// ## Usage {#bslh_hashtuple-usage}
42///
43///
44/// This section illustrates intended usage of this component.
45///
46/// ### Example 1: Hashing a Tuple of Integer Values {#bslh_hashtuple-example-1-hashing-a-tuple-of-integer-values}
47///
48///
49/// Suppose one must compute has that combines the hashes of several integer
50/// values, each of a different type:
51/// @code
52/// char c = 'a';
53/// short s = static_cast<short>(1);
54/// int i = 2;
55/// long l = 3L;
56/// @endcode
57/// First, we can make that calculation by repeated invocations of a
58/// 'bslh::DefaultHashAlogorithm object:
59/// @code
60/// bslh::DefaultHashAlgorithm hasherS;
61/// hasherS(&c, sizeof(char));
62/// hasherS(&s, sizeof(short));
63/// hasherS(&i, sizeof(int));
64/// hasherS(&l, sizeof(long));
65///
66/// bslh::DefaultHashAlgorithm::result_type hashS = hasherS.computeHash();
67/// @endcode
68/// Now, the same calculation can be expressed more concisely if those same
69/// values are contained in a single `std::tuple` object.
70/// @code
71/// std::tuple<char, short, int, long> t = std::make_tuple(c, s, i, l);
72///
73/// bslh::DefaultHashAlgorithm hasherT;
74/// bslh::hashAppend(hasherT, t);
75///
76/// bslh::DefaultHashAlgorithm::result_type hashT = hasherT.computeHash();
77/// @endcode
78/// Finally, we confirm that we computed the same result.
79/// @code
80/// assert(hashS == hashT);
81/// @endcode
82/// @}
83/** @} */
84/** @} */
85
86/** @addtogroup bsl
87 * @{
88 */
89/** @addtogroup bslh
90 * @{
91 */
92/** @addtogroup bslh_hashtuple
93 * @{
94 */
95
96#include <bslscm_version.h>
97
99
100#ifdef BSLS_LIBRARYFEATURES_HAS_CPP11_TUPLE
101
102#include <bslh_hash.h>
103
104#include <type_traits> // 'std::remove_reference'
105#include <tuple> // 'std::tuple'
106#include <cstddef> // 'std::size_t'
107
108
109namespace bslh {
110
111 // =====================
112 // struct hashTuple_Util
113 // =====================
114
115template <std::size_t BACK_INDEX, class HASH_ALGORITHM, class TUPLE_TYPE>
116struct hashTuple_Util
117{
118 // CLASS METHODS
119
120 /// Invoke the (appropriate) `hashAppend` function using the specified
121 /// `algorithm` and the "current" element of the specified `input` tuple
122 /// and then visit the next element. The index of the current element
123 /// is the size of (template parameter) `TUPLE_TYPE` minus (template
124 /// parameter) `BACK_INDEX`. `BACK_INDEX` is reduced on each recursion
125 /// and eventually, when `BACK_INDEX` is 0, a "do nothing" function is
126 /// called to stop the recursion.
127 static void visit(HASH_ALGORITHM& algorithm, const TUPLE_TYPE& input);
128};
129
130 // The partial specialization that stops the recursion.
131
132template <class HASH_ALGORITHM, class TUPLE_TYPE>
133struct hashTuple_Util<0, HASH_ALGORITHM, TUPLE_TYPE>
134{
135 // CLASS METHODS
136
137 /// Do nothing -- ignore the specified `algorithm`, ignore the specified
138 /// `input`, do not try to visit the "next" element -- and return. Note
139 /// that this function is called only after the last element of `input`
140 /// has been visited.
141 static void visit(HASH_ALGORITHM& algorithm, const TUPLE_TYPE& input);
142};
143
144// FREE FUNCTIONS
145
146/// Invoke `hashAppend`, with the specified `algorithm`, on each element of
147/// the specified `input` in order of increasing index as defined by
148/// `std::get`.
149template <class HASH_ALGORITHM, class ... TYPE>
150void hashAppend(HASH_ALGORITHM& algorithm, const std::tuple<TYPE ...> &input);
151
152// ============================================================================
153// INLINE DEFINITIONS
154// ============================================================================
155
156 // ---------------------
157 // struct hashTuple_Util
158 // ---------------------
159
160template <std::size_t BACK_INDEX, class HASH_ALGORITHM, class TUPLE_TYPE>
161inline
162void hashTuple_Util<BACK_INDEX, HASH_ALGORITHM, TUPLE_TYPE>::visit(
163 HASH_ALGORITHM& algorithm,
164 const TUPLE_TYPE& input)
165{
166 // Hash current element.
167
168 const std::size_t tupleSize = std::tuple_size<TUPLE_TYPE>::value;
169 const std::size_t index = tupleSize - BACK_INDEX;
170
171 hashAppend(algorithm, std::get<index>(input));
172
173 // Visit next element.
174
175 const std::size_t nextBackIndex = BACK_INDEX - 1;
176
177 hashTuple_Util<nextBackIndex, HASH_ALGORITHM, TUPLE_TYPE>::visit(algorithm,
178 input);
179}
180
181template <class HASH_ALGORITHM, class TUPLE_TYPE>
182inline
183void hashTuple_Util<0, HASH_ALGORITHM, TUPLE_TYPE>::visit(HASH_ALGORITHM& ,
184 const TUPLE_TYPE& )
185{
186}
187
188// FREE FUNCTIONS
189template <class HASH_ALGORITHM, class ... TYPE>
190inline
191void
192hashAppend(HASH_ALGORITHM& algorithm, const std::tuple<TYPE ...> &input)
193{
194 using TupleType = typename std::remove_reference<decltype(input)>::type;
195
196 const std::size_t tupleSize = std::tuple_size<TupleType>::value;
197
198 if (0 == tupleSize) {
199 return; // RETURN
200 }
201
202 hashTuple_Util<tupleSize, HASH_ALGORITHM, TupleType>::visit(algorithm,
203 input);
204}
205
206} // close package namespace
207
208
209#endif // BSLS_LIBRARYFEATURES_HAS_CPP11_TUPLE
210#endif
211
212// ----------------------------------------------------------------------------
213// Copyright 2021 Bloomberg Finance L.P.
214//
215// Licensed under the Apache License, Version 2.0 (the "License");
216// you may not use this file except in compliance with the License.
217// You may obtain a copy of the License at
218//
219// http://www.apache.org/licenses/LICENSE-2.0
220//
221// Unless required by applicable law or agreed to in writing, software
222// distributed under the License is distributed on an "AS IS" BASIS,
223// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
224// See the License for the specific language governing permissions and
225// limitations under the License.
226// ----------------------------- END-OF-FILE ----------------------------------
227
228/** @} */
229/** @} */
230/** @} */
#define BSLS_IDENT(str)
Definition bsls_ident.h:195
bsl::invoke_result< t_VISITOR &, typenamebsl::variant_alternative< 0, t_VARIANT >::type & >::type visit(t_VISITOR &visitor, t_VARIANT &variant)
Definition bslstl_variant.h:2262
Definition bslh_defaulthashalgorithm.h:339
bsl::enable_if<(bsl::is_integral< TYPE >::value||bsl::is_pointer< TYPE >::value||bsl::is_enum< TYPE >::value)&&!bsl::is_same< TYPE, bool >::value >::type hashAppend(HASH_ALGORITHM &hashAlg, TYPE input)
Definition bslh_hash.h:638