From 44970ed96eafc2f84056850fa5cb36d8349abacd Mon Sep 17 00:00:00 2001 From: Ichthyostega Date: Thu, 3 Apr 2014 22:43:35 +0200 Subject: [PATCH] unsuccessful attempt to bridge between std::hash and boost::hash_value (Ticket #722) --- src/lib/hash-indexed.hpp | 21 ++++ src/lib/hash-standard.hpp | 104 +++++++++++++++++++ src/proc/mobject/session/placement-index.hpp | 14 +++ 3 files changed, 139 insertions(+) create mode 100644 src/lib/hash-standard.hpp diff --git a/src/lib/hash-indexed.hpp b/src/lib/hash-indexed.hpp index 5a74975ee..6c547b31c 100644 --- a/src/lib/hash-indexed.hpp +++ b/src/lib/hash-indexed.hpp @@ -55,6 +55,7 @@ #define LIB_HASH_INDEXED_H #include "lib/hash-value.h" +#include "lib/hash-standard.hpp" extern "C" { #include "lib/luid.h" @@ -208,4 +209,24 @@ namespace lib { } // namespace lib + + +/////////////////////////////////////////////////////////////////////////TICKET #722 : should provide a generic bridge to use hash_value + +// The following doesn't work as expected, probably because of sub type relationship not being detected when picking a template specialisation +// see also hash-standard.hpp + +//namespace std { +// +// template +// struct hash > +// { +// size_t +// operator() (lib::HashIndexed const& val) const noexcept +// { +// return hash_value(val); +// } +// }; +// +//} #endif diff --git a/src/lib/hash-standard.hpp b/src/lib/hash-standard.hpp new file mode 100644 index 000000000..b7be71430 --- /dev/null +++ b/src/lib/hash-standard.hpp @@ -0,0 +1,104 @@ +/* + HASH-STANDARD.hpp - allow use both of std and boost hasher implementations + + Copyright (C) Lumiera.org + 2014, Hermann Vosseler + + This program is free software; you can redistribute it and/or + modify it under the terms of the GNU General Public License as + published by the Free Software Foundation; either version 2 of + the License, or (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + +*/ + + +/** @file hash-standard.hpp + ** Helper to use a single extension point for specialised hash functions. + ** With the switch to C++11, there are now two competing quasi standard frameworks + ** for defining individual hasher functions: the \c std::hash functor and \c . + ** The standard library hasher is used by the (new) STL hashtables and requires an explicit + ** specialisation of \c std::hash, while the boost hash automatically picks up an + ** free function `hash_value(MyType const&)`. Additionally, Boost ships with a large collection + ** of predefined hash functions for various combinations of standard containers and custom types. + ** To add to this venerable mess, the standard hash defines a default specialisation which + ** triggers a static assertion and halts compilation, in case no custom specialisation + ** can be found. + ** + ** In the Lumiera code base, the habit is to define a free function \c hash_value alongside with + ** custom data types. This helper uses metaprogramming to generate a bridge from the standard hasher + ** to use this boost-style custom hash function if applicable. + ** + ** @todo 4/2014 doesn't work as expected. My suspicion is that in the actual use case (PlacementIndex), + ** the type providing the hasher is mixed in through inheritance, and the template specialisation + ** for this base type is not considered on lookup. ///////TICKET #722 + ** + ** @see HashIndexed + ** @see LUID + ** + */ + + + +#ifndef LIB_HASH_STANDARD_H +#define LIB_HASH_STANDARD_H + +#include "lib/hash-value.h" +#include "lib/meta/util.hpp" + +#include +//#include +#include + +namespace lib { +namespace meta { + + + template +struct has_boost_hash_subst { typedef void* Type; }; + + + + template + struct provides_BoostHasher + { + template + static Yes_t check(typename has_boost_hash_subst::Type); + template + static No_t check(...); + + enum{ value = (sizeof(Yes_t)==sizeof(check(nullptr))) }; + }; + +}} + +namespace std { + + /////////////////////////////////////////////////////////////////////////TICKET #722 : attempt to provide a generic bridge to use hash_value + // + // this was my first attempt 4/2014, but doesn't work, probably because of the actual ID being inherited + // see also the attempt at the bottom of hash-indexed.hpp + + + template + struct hash< boost::enable_if, + TY > > + { + size_t + operator() (TY const& val) const noexcept + { + return hash_value(val); + } + }; + + +} +#endif diff --git a/src/proc/mobject/session/placement-index.hpp b/src/proc/mobject/session/placement-index.hpp index aa2d3363a..a4a4ac238 100644 --- a/src/proc/mobject/session/placement-index.hpp +++ b/src/proc/mobject/session/placement-index.hpp @@ -117,6 +117,20 @@ #include #include +namespace std { + + /////////////////////////////////////////////////////////////////////////TICKET #722 : should provide a generic bridge to use hash_value + template<> + struct hash + { + size_t + operator() (proc::mobject::PlacementMO::ID const& val) const noexcept + { + return hash_value(val); + } + }; +} + namespace proc { namespace mobject {