BDE 4.39.x 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.
139 ///
140 /// \note Note that this function is called only after the last element of `input`
141 /// has been visited.
142 static void visit(HASH_ALGORITHM& algorithm, const TUPLE_TYPE& input);
143};
144
145// FREE FUNCTIONS
146
147/// Invoke `hashAppend`, with the specified `algorithm`, on each element of
148/// the specified `input` in order of increasing index as defined by
149/// `std::get`.
150template <class HASH_ALGORITHM, class ... TYPE>
151void hashAppend(HASH_ALGORITHM& algorithm, const std::tuple<TYPE ...> &input);
152
153// ============================================================================
154// INLINE DEFINITIONS
155// ============================================================================
156
157 // ---------------------
158 // struct hashTuple_Util
159 // ---------------------
160
161template <std::size_t BACK_INDEX, class HASH_ALGORITHM, class TUPLE_TYPE>
162inline
163void hashTuple_Util<BACK_INDEX, HASH_ALGORITHM, TUPLE_TYPE>::visit(
164 HASH_ALGORITHM& algorithm,
165 const TUPLE_TYPE& input)
166{
167 // Hash current element.
168
169 const std::size_t tupleSize = std::tuple_size<TUPLE_TYPE>::value;
170 const std::size_t index = tupleSize - BACK_INDEX;
171
172 hashAppend(algorithm, std::get<index>(input));
173
174 // Visit next element.
175
176 const std::size_t nextBackIndex = BACK_INDEX - 1;
177
178 hashTuple_Util<nextBackIndex, HASH_ALGORITHM, TUPLE_TYPE>::visit(algorithm,
179 input);
180}
181
182template <class HASH_ALGORITHM, class TUPLE_TYPE>
183inline
184void hashTuple_Util<0, HASH_ALGORITHM, TUPLE_TYPE>::visit(HASH_ALGORITHM& ,
185 const TUPLE_TYPE& )
186{
187}
188
189// FREE FUNCTIONS
190template <class HASH_ALGORITHM, class ... TYPE>
191inline
192void
193hashAppend(HASH_ALGORITHM& algorithm, const std::tuple<TYPE ...> &input)
194{
195 using TupleType = typename std::remove_reference<decltype(input)>::type;
196
197 const std::size_t tupleSize = std::tuple_size<TupleType>::value;
198
199 if (0 == tupleSize) {
200 return; // RETURN
201 }
202
203 hashTuple_Util<tupleSize, HASH_ALGORITHM, TupleType>::visit(algorithm,
204 input);
205}
206
207} // close package namespace
208
209
210#endif // BSLS_LIBRARYFEATURES_HAS_CPP11_TUPLE
211#endif
212
213// ----------------------------------------------------------------------------
214// Copyright 2021 Bloomberg Finance L.P.
215//
216// Licensed under the Apache License, Version 2.0 (the "License");
217// you may not use this file except in compliance with the License.
218// You may obtain a copy of the License at
219//
220// http://www.apache.org/licenses/LICENSE-2.0
221//
222// Unless required by applicable law or agreed to in writing, software
223// distributed under the License is distributed on an "AS IS" BASIS,
224// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
225// See the License for the specific language governing permissions and
226// limitations under the License.
227// ----------------------------- END-OF-FILE ----------------------------------
228
229/** @} */
230/** @} */
231/** @} */
#define BSLS_IDENT(str)
BSLS_IDENT() - insert string into .comment binary segment (if supported)
Definition bsls_ident.h:238
bsl::invoke_result< t_VISITOR &, typenamebsl::variant_alternative< 0, t_VARIANT >::type & >::type visit(t_VISITOR &visitor, t_VARIANT &variant)
Definition bslstl_variant.h:2359
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:643