// bslh_hashtuple.h -*-C++-*- #ifndef INCLUDED_BSLH_HASHTUPLE #define INCLUDED_BSLH_HASHTUPLE #include <bsls_ident.h> BSLS_IDENT("$Id: $") //@PURPOSE: Provide 'hashAppend' for 'std::tuple'. // //@DESCRIPTION: This component provides a free function template, // 'bslh::hashAppend', overloaded for the 'std::tuple' class template. // Including this function allows for 'std::tuple' types (and types that // contain them) to be used as keys in BDE hashed containers. // // Note that use of this component requires that the language standard be 2011 // or later, as that is when 'std::tuple' first appears. // ///Usage ///----- // This section illustrates intended usage of this component. // ///Example 1: Hashing a Tuple of Integer Values /// - - - - - - - - - - - - - - - - - - - - - - // Suppose one must compute has that combines the hashes of several integer // values, each of a different type: //.. // char c = 'a'; // short s = static_cast<short>(1); // int i = 2; // long l = 3L; //.. // First, we can make that calculation by repeated invocations of a // 'bslh::DefaultHashAlogorithm object: //.. // bslh::DefaultHashAlgorithm hasherS; // hasherS(&c, sizeof(char)); // hasherS(&s, sizeof(short)); // hasherS(&i, sizeof(int)); // hasherS(&l, sizeof(long)); // // bslh::DefaultHashAlgorithm::result_type hashS = hasherS.computeHash(); //.. // Now, the same calculation can be expressed more concisely if those same // values are contained in a single 'std::tuple' object. //.. // std::tuple<char, short, int, long> t = std::make_tuple(c, s, i, l); // // bslh::DefaultHashAlgorithm hasherT; // bslh::hashAppend(hasherT, t); // // bslh::DefaultHashAlgorithm::result_type hashT = hasherT.computeHash(); //.. // Finally, we confirm that we computed the same result. //.. // assert(hashS == hashT); //.. #include <bslscm_version.h> #include <bsls_libraryfeatures.h> #ifdef BSLS_LIBRARYFEATURES_HAS_CPP11_TUPLE #include <bslh_hash.h> #include <type_traits> // 'std::remove_reference' #include <tuple> // 'std::tuple' #include <cstddef> // 'std::size_t' namespace BloombergLP { namespace bslh { // ===================== // struct hashTuple_Util // ===================== template <std::size_t BACK_INDEX, class HASH_ALGORITHM, class TUPLE_TYPE> struct hashTuple_Util { // CLASS METHODS static void visit(HASH_ALGORITHM& algorithm, const TUPLE_TYPE& input); // Invoke the (appropriate) 'hashAppend' function using the specified // 'algorithm' and the "current" element of the specified 'input' tuple // and then visit the next element. The index of the current element // is the size of (template parameter) 'TUPLE_TYPE' minus (template // parameter) 'BACK_INDEX'. 'BACK_INDEX' is reduced on each recursion // and eventually, when 'BACK_INDEX' is 0, a "do nothing" function is // called to stop the recursion. }; // The partial specialization that stops the recursion. template <class HASH_ALGORITHM, class TUPLE_TYPE> struct hashTuple_Util<0, HASH_ALGORITHM, TUPLE_TYPE> { // CLASS METHODS static void visit(HASH_ALGORITHM& algorithm, const TUPLE_TYPE& input); // Do nothing -- ignore the specified 'algorithm', ignore the specified // 'input', do not try to visit the "next" element -- and return. Note // that this function is called only after the last element of 'input' // has been visited. }; // FREE FUNCTIONS template <class HASH_ALGORITHM, class ... TYPE> void hashAppend(HASH_ALGORITHM& algorithm, const std::tuple<TYPE ...> &input); // Invoke 'hashAppend', with the specified 'algorithm', on each element of // the specified 'input' in order of increasing index as defined by // 'std::get'. // ============================================================================ // INLINE DEFINITIONS // ============================================================================ // --------------------- // struct hashTuple_Util // --------------------- template <std::size_t BACK_INDEX, class HASH_ALGORITHM, class TUPLE_TYPE> inline void hashTuple_Util<BACK_INDEX, HASH_ALGORITHM, TUPLE_TYPE>::visit( HASH_ALGORITHM& algorithm, const TUPLE_TYPE& input) { // Hash current element. const std::size_t tupleSize = std::tuple_size<TUPLE_TYPE>::value; const std::size_t index = tupleSize - BACK_INDEX; hashAppend(algorithm, std::get<index>(input)); // Visit next element. const std::size_t nextBackIndex = BACK_INDEX - 1; hashTuple_Util<nextBackIndex, HASH_ALGORITHM, TUPLE_TYPE>::visit(algorithm, input); } template <class HASH_ALGORITHM, class TUPLE_TYPE> inline void hashTuple_Util<0, HASH_ALGORITHM, TUPLE_TYPE>::visit(HASH_ALGORITHM& , const TUPLE_TYPE& ) { } // FREE FUNCTIONS template <class HASH_ALGORITHM, class ... TYPE> inline void hashAppend(HASH_ALGORITHM& algorithm, const std::tuple<TYPE ...> &input) { using TupleType = typename std::remove_reference<decltype(input)>::type; const std::size_t tupleSize = std::tuple_size<TupleType>::value; if (0 == tupleSize) { return; // RETURN } hashTuple_Util<tupleSize, HASH_ALGORITHM, TupleType>::visit(algorithm, input); } } // close package namespace } // close enterprise namespace #endif // BSLS_LIBRARYFEATURES_HAS_CPP11_TUPLE #endif // ---------------------------------------------------------------------------- // Copyright 2021 Bloomberg Finance L.P. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // ----------------------------- END-OF-FILE ----------------------------------