aboutsummaryrefslogtreecommitdiff
path: root/cutl/details/boost/functional
diff options
context:
space:
mode:
Diffstat (limited to 'cutl/details/boost/functional')
-rw-r--r--cutl/details/boost/functional/hash/detail/float_functions.hpp90
-rw-r--r--cutl/details/boost/functional/hash/detail/hash_float.hpp206
-rw-r--r--cutl/details/boost/functional/hash/detail/hash_float_generic.hpp91
-rw-r--r--cutl/details/boost/functional/hash/detail/hash_float_x86.hpp56
-rw-r--r--cutl/details/boost/functional/hash/extensions.hpp111
-rw-r--r--cutl/details/boost/functional/hash/hash.hpp200
6 files changed, 480 insertions, 274 deletions
diff --git a/cutl/details/boost/functional/hash/detail/float_functions.hpp b/cutl/details/boost/functional/hash/detail/float_functions.hpp
index 0686928..1d5a02b 100644
--- a/cutl/details/boost/functional/hash/detail/float_functions.hpp
+++ b/cutl/details/boost/functional/hash/detail/float_functions.hpp
@@ -13,6 +13,94 @@
# pragma once
#endif
+// Set BOOST_HASH_CONFORMANT_FLOATS to 1 for libraries known to have
+// sufficiently good floating point support to not require any
+// workarounds.
+//
+// When set to 0, the library tries to automatically
+// use the best available implementation. This normally works well, but
+// breaks when ambiguities are created by odd namespacing of the functions.
+//
+// Note that if this is set to 0, the library should still take full
+// advantage of the platform's floating point support.
+
+#if defined(__SGI_STL_PORT) || defined(_STLPORT_VERSION)
+# define BOOST_HASH_CONFORMANT_FLOATS 0
+#elif defined(__LIBCOMO__)
+# define BOOST_HASH_CONFORMANT_FLOATS 0
+#elif defined(__STD_RWCOMPILER_H__) || defined(_RWSTD_VER)
+// Rogue Wave library:
+# define BOOST_HASH_CONFORMANT_FLOATS 0
+#elif defined(_LIBCPP_VERSION)
+// libc++
+# define BOOST_HASH_CONFORMANT_FLOATS 1
+#elif defined(__GLIBCPP__) || defined(__GLIBCXX__)
+// GNU libstdc++ 3
+# if defined(__GNUC__) && __GNUC__ >= 4
+# define BOOST_HASH_CONFORMANT_FLOATS 1
+# else
+# define BOOST_HASH_CONFORMANT_FLOATS 0
+# endif
+#elif defined(__STL_CONFIG_H)
+// generic SGI STL
+# define BOOST_HASH_CONFORMANT_FLOATS 0
+#elif defined(__MSL_CPP__)
+// MSL standard lib:
+# define BOOST_HASH_CONFORMANT_FLOATS 0
+#elif defined(__IBMCPP__)
+// VACPP std lib (probably conformant for much earlier version).
+# if __IBMCPP__ >= 1210
+# define BOOST_HASH_CONFORMANT_FLOATS 1
+# else
+# define BOOST_HASH_CONFORMANT_FLOATS 0
+# endif
+#elif defined(MSIPL_COMPILE_H)
+// Modena C++ standard library
+# define BOOST_HASH_CONFORMANT_FLOATS 0
+#elif (defined(_YVALS) && !defined(__IBMCPP__)) || defined(_CPPLIB_VER)
+// Dinkumware Library (this has to appear after any possible replacement libraries):
+# if _CPPLIB_VER >= 405
+# define BOOST_HASH_CONFORMANT_FLOATS 1
+# else
+# define BOOST_HASH_CONFORMANT_FLOATS 0
+# endif
+#else
+# define BOOST_HASH_CONFORMANT_FLOATS 0
+#endif
+
+#if BOOST_HASH_CONFORMANT_FLOATS
+
+// The standard library is known to be compliant, so don't use the
+// configuration mechanism.
+
+namespace cutl_details_boost {
+ namespace hash_detail {
+ template <typename Float>
+ struct call_ldexp {
+ typedef Float float_type;
+ inline Float operator()(Float x, int y) const {
+ return std::ldexp(x, y);
+ }
+ };
+
+ template <typename Float>
+ struct call_frexp {
+ typedef Float float_type;
+ inline Float operator()(Float x, int* y) const {
+ return std::frexp(x, y);
+ }
+ };
+
+ template <typename Float>
+ struct select_hash_type
+ {
+ typedef Float type;
+ };
+ }
+}
+
+#else // BOOST_HASH_CONFORMANT_FLOATS == 0
+
// The C++ standard requires that the C float functions are overloarded
// for float, double and long double in the std namespace, but some of the older
// library implementations don't support this. On some that don't, the C99
@@ -243,4 +331,6 @@ namespace cutl_details_boost
}
}
+#endif // BOOST_HASH_CONFORMANT_FLOATS
+
#endif
diff --git a/cutl/details/boost/functional/hash/detail/hash_float.hpp b/cutl/details/boost/functional/hash/detail/hash_float.hpp
index dafec9a..aaa49d9 100644
--- a/cutl/details/boost/functional/hash/detail/hash_float.hpp
+++ b/cutl/details/boost/functional/hash/detail/hash_float.hpp
@@ -1,5 +1,5 @@
-// Copyright 2005-2009 Daniel James.
+// Copyright 2005-2012 Daniel James.
// Distributed under the Boost Software License, Version 1.0. (See accompanying
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
@@ -13,21 +13,19 @@
#include <cutl/details/boost/config.hpp>
#include <cutl/details/boost/functional/hash/detail/float_functions.hpp>
#include <cutl/details/boost/functional/hash/detail/limits.hpp>
+#include <cutl/details/boost/utility/enable_if.hpp>
#include <cutl/details/boost/integer/static_log2.hpp>
#include <cutl/details/boost/cstdint.hpp>
#include <cutl/details/boost/assert.hpp>
+#include <cutl/details/boost/limits.hpp>
+#include <cstring>
-// Include hash implementation for the current platform.
-
-// Cygwn
-#if defined(__CYGWIN__)
-# if defined(__i386__) || defined(_M_IX86)
-# include <cutl/details/boost/functional/hash/detail/hash_float_x86.hpp>
-# else
-# include <cutl/details/boost/functional/hash/detail/hash_float_generic.hpp>
-# endif
-#else
-# include <cutl/details/boost/functional/hash/detail/hash_float_generic.hpp>
+#if defined(BOOST_MSVC)
+#pragma warning(push)
+#if BOOST_MSVC >= 1400
+#pragma warning(disable:6294) // Ill-defined for-loop: initial condition does
+ // not satisfy test. Loop body not executed
+#endif
#endif
// Can we use fpclassify?
@@ -50,6 +48,159 @@
# define BOOST_HASH_USE_FPCLASSIFY 0
#endif
+namespace cutl_details_boost
+{
+ namespace hash_detail
+ {
+ inline void hash_float_combine(std::size_t& seed, std::size_t value)
+ {
+ seed ^= value + (seed<<6) + (seed>>2);
+ }
+
+ ////////////////////////////////////////////////////////////////////////
+ // Binary hash function
+ //
+ // Only used for floats with known iec559 floats, and certain values in
+ // numeric_limits
+
+ inline std::size_t hash_binary(char* ptr, std::size_t length)
+ {
+ std::size_t seed = 0;
+
+ if (length >= sizeof(std::size_t)) {
+ seed = *(std::size_t*) ptr;
+ length -= sizeof(std::size_t);
+ ptr += sizeof(std::size_t);
+
+ while(length >= sizeof(std::size_t)) {
+ std::size_t buffer = 0;
+ std::memcpy(&buffer, ptr, sizeof(std::size_t));
+ hash_float_combine(seed, buffer);
+ length -= sizeof(std::size_t);
+ ptr += sizeof(std::size_t);
+ }
+ }
+
+ if (length > 0) {
+ std::size_t buffer = 0;
+ std::memcpy(&buffer, ptr, length);
+ hash_float_combine(seed, buffer);
+ }
+
+ return seed;
+ }
+
+ template <typename Float>
+ inline std::size_t float_hash_impl(Float v,
+ BOOST_DEDUCED_TYPENAME cutl_details_boost::enable_if_c<
+ std::numeric_limits<Float>::is_iec559 &&
+ std::numeric_limits<Float>::digits == 24 &&
+ std::numeric_limits<Float>::radix == 2 &&
+ std::numeric_limits<Float>::max_exponent == 128,
+ int>::type
+ )
+ {
+ return hash_binary((char*) &v, 4);
+ }
+
+
+ template <typename Float>
+ inline std::size_t float_hash_impl(Float v,
+ BOOST_DEDUCED_TYPENAME cutl_details_boost::enable_if_c<
+ std::numeric_limits<Float>::is_iec559 &&
+ std::numeric_limits<Float>::digits == 53 &&
+ std::numeric_limits<Float>::radix == 2 &&
+ std::numeric_limits<Float>::max_exponent == 1024,
+ int>::type
+ )
+ {
+ return hash_binary((char*) &v, 8);
+ }
+
+ template <typename Float>
+ inline std::size_t float_hash_impl(Float v,
+ BOOST_DEDUCED_TYPENAME cutl_details_boost::enable_if_c<
+ std::numeric_limits<Float>::is_iec559 &&
+ std::numeric_limits<Float>::digits == 64 &&
+ std::numeric_limits<Float>::radix == 2 &&
+ std::numeric_limits<Float>::max_exponent == 16384,
+ int>::type
+ )
+ {
+ return hash_binary((char*) &v, 10);
+ }
+
+ template <typename Float>
+ inline std::size_t float_hash_impl(Float v,
+ BOOST_DEDUCED_TYPENAME cutl_details_boost::enable_if_c<
+ std::numeric_limits<Float>::is_iec559 &&
+ std::numeric_limits<Float>::digits == 113 &&
+ std::numeric_limits<Float>::radix == 2 &&
+ std::numeric_limits<Float>::max_exponent == 16384,
+ int>::type
+ )
+ {
+ return hash_binary((char*) &v, 16);
+ }
+
+ ////////////////////////////////////////////////////////////////////////
+ // Portable hash function
+ //
+ // Used as a fallback when the binary hash function isn't supported.
+
+ template <class T>
+ inline std::size_t float_hash_impl2(T v)
+ {
+ cutl_details_boost::hash_detail::call_frexp<T> frexp;
+ cutl_details_boost::hash_detail::call_ldexp<T> ldexp;
+
+ int exp = 0;
+
+ v = frexp(v, &exp);
+
+ // A postive value is easier to hash, so combine the
+ // sign with the exponent and use the absolute value.
+ if(v < 0) {
+ v = -v;
+ exp += limits<T>::max_exponent -
+ limits<T>::min_exponent;
+ }
+
+ v = ldexp(v, limits<std::size_t>::digits);
+ std::size_t seed = static_cast<std::size_t>(v);
+ v -= static_cast<T>(seed);
+
+ // ceiling(digits(T) * log2(radix(T))/ digits(size_t)) - 1;
+ std::size_t const length
+ = (limits<T>::digits *
+ cutl_details_boost::static_log2<limits<T>::radix>::value
+ + limits<std::size_t>::digits - 1)
+ / limits<std::size_t>::digits;
+
+ for(std::size_t i = 0; i != length; ++i)
+ {
+ v = ldexp(v, limits<std::size_t>::digits);
+ std::size_t part = static_cast<std::size_t>(v);
+ v -= static_cast<T>(part);
+ hash_float_combine(seed, part);
+ }
+
+ hash_float_combine(seed, exp);
+
+ return seed;
+ }
+
+#if !defined(BOOST_HASH_DETAIL_TEST_WITHOUT_GENERIC)
+ template <class T>
+ inline std::size_t float_hash_impl(T v, ...)
+ {
+ typedef BOOST_DEDUCED_TYPENAME select_hash_type<T>::type type;
+ return float_hash_impl2(static_cast<type>(v));
+ }
+#endif
+ }
+}
+
#if BOOST_HASH_USE_FPCLASSIFY
#include <cutl/details/boost/config/no_tr1/cmath.hpp>
@@ -61,8 +212,15 @@ namespace cutl_details_boost
template <class T>
inline std::size_t float_hash_value(T v)
{
+#if defined(fpclassify)
+ switch (fpclassify(v))
+#elif BOOST_HASH_CONFORMANT_FLOATS
+ switch (std::fpclassify(v))
+#else
using namespace std;
- switch (fpclassify(v)) {
+ switch (fpclassify(v))
+#endif
+ {
case FP_ZERO:
return 0;
case FP_INFINITE:
@@ -71,7 +229,7 @@ namespace cutl_details_boost
return (std::size_t)(-3);
case FP_NORMAL:
case FP_SUBNORMAL:
- return float_hash_impl(v);
+ return float_hash_impl(v, 0);
default:
BOOST_ASSERT(0);
return 0;
@@ -87,9 +245,23 @@ namespace cutl_details_boost
namespace hash_detail
{
template <class T>
+ inline bool is_zero(T v)
+ {
+#if !defined(__GNUC__)
+ return v == 0;
+#else
+ // GCC's '-Wfloat-equal' will complain about comparing
+ // v to 0, but because it disables warnings for system
+ // headers it won't complain if you use std::equal_to to
+ // compare with 0. Resulting in this silliness:
+ return std::equal_to<T>()(v, 0);
+#endif
+ }
+
+ template <class T>
inline std::size_t float_hash_value(T v)
{
- return v == 0 ? 0 : float_hash_impl(v);
+ return cutl_details_boost::hash_detail::is_zero(v) ? 0 : float_hash_impl(v, 0);
}
}
}
@@ -98,4 +270,8 @@ namespace cutl_details_boost
#undef BOOST_HASH_USE_FPCLASSIFY
+#if defined(BOOST_MSVC)
+#pragma warning(pop)
+#endif
+
#endif
diff --git a/cutl/details/boost/functional/hash/detail/hash_float_generic.hpp b/cutl/details/boost/functional/hash/detail/hash_float_generic.hpp
deleted file mode 100644
index 295b620..0000000
--- a/cutl/details/boost/functional/hash/detail/hash_float_generic.hpp
+++ /dev/null
@@ -1,91 +0,0 @@
-
-// Copyright 2005-2009 Daniel James.
-// Distributed under the Boost Software License, Version 1.0. (See accompanying
-// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
-
-// A general purpose hash function for non-zero floating point values.
-
-#if !defined(BOOST_FUNCTIONAL_HASH_DETAIL_HASH_FLOAT_GENERIC_HEADER)
-#define BOOST_FUNCTIONAL_HASH_DETAIL_HASH_FLOAT_GENERIC_HEADER
-
-#include <cutl/details/boost/functional/hash/detail/float_functions.hpp>
-#include <cutl/details/boost/integer/static_log2.hpp>
-#include <cutl/details/boost/functional/hash/detail/limits.hpp>
-
-#if defined(_MSC_VER) && (_MSC_VER >= 1020)
-# pragma once
-#endif
-
-#if defined(BOOST_MSVC)
-#pragma warning(push)
-#if BOOST_MSVC >= 1400
-#pragma warning(disable:6294) // Ill-defined for-loop: initial condition does
- // not satisfy test. Loop body not executed
-#endif
-#endif
-
-namespace cutl_details_boost
-{
- namespace hash_detail
- {
- inline void hash_float_combine(std::size_t& seed, std::size_t value)
- {
- seed ^= value + (seed<<6) + (seed>>2);
- }
-
- template <class T>
- inline std::size_t float_hash_impl2(T v)
- {
- cutl_details_boost::hash_detail::call_frexp<T> frexp;
- cutl_details_boost::hash_detail::call_ldexp<T> ldexp;
-
- int exp = 0;
-
- v = frexp(v, &exp);
-
- // A postive value is easier to hash, so combine the
- // sign with the exponent and use the absolute value.
- if(v < 0) {
- v = -v;
- exp += limits<T>::max_exponent -
- limits<T>::min_exponent;
- }
-
- v = ldexp(v, limits<std::size_t>::digits);
- std::size_t seed = static_cast<std::size_t>(v);
- v -= static_cast<T>(seed);
-
- // ceiling(digits(T) * log2(radix(T))/ digits(size_t)) - 1;
- std::size_t const length
- = (limits<T>::digits *
- cutl_details_boost::static_log2<limits<T>::radix>::value
- + limits<std::size_t>::digits - 1)
- / limits<std::size_t>::digits;
-
- for(std::size_t i = 0; i != length; ++i)
- {
- v = ldexp(v, limits<std::size_t>::digits);
- std::size_t part = static_cast<std::size_t>(v);
- v -= static_cast<T>(part);
- hash_float_combine(seed, part);
- }
-
- hash_float_combine(seed, exp);
-
- return seed;
- }
-
- template <class T>
- inline std::size_t float_hash_impl(T v)
- {
- typedef BOOST_DEDUCED_TYPENAME select_hash_type<T>::type type;
- return float_hash_impl2(static_cast<type>(v));
- }
- }
-}
-
-#if defined(BOOST_MSVC)
-#pragma warning(pop)
-#endif
-
-#endif
diff --git a/cutl/details/boost/functional/hash/detail/hash_float_x86.hpp b/cutl/details/boost/functional/hash/detail/hash_float_x86.hpp
deleted file mode 100644
index 6a70556..0000000
--- a/cutl/details/boost/functional/hash/detail/hash_float_x86.hpp
+++ /dev/null
@@ -1,56 +0,0 @@
-
-// Copyright 2005-2009 Daniel James.
-// Distributed under the Boost Software License, Version 1.0. (See accompanying
-// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
-
-// A non-portable hash function form non-zero floats on x86.
-//
-// Even if you're on an x86 platform, this might not work if their floating
-// point isn't set up as this expects. So this should only be used if it's
-// absolutely certain that it will work.
-
-#if !defined(BOOST_FUNCTIONAL_HASH_DETAIL_HASH_FLOAT_X86_HEADER)
-#define BOOST_FUNCTIONAL_HASH_DETAIL_HASH_FLOAT_X86_HEADER
-
-#include <cutl/details/boost/cstdint.hpp>
-
-#if defined(_MSC_VER) && (_MSC_VER >= 1020)
-# pragma once
-#endif
-
-namespace cutl_details_boost
-{
- namespace hash_detail
- {
- inline void hash_float_combine(std::size_t& seed, std::size_t value)
- {
- seed ^= value + (seed<<6) + (seed>>2);
- }
-
- inline std::size_t float_hash_impl(float v)
- {
- cutl_details_boost::uint32_t* ptr = (cutl_details_boost::uint32_t*)&v;
- std::size_t seed = *ptr;
- return seed;
- }
-
- inline std::size_t float_hash_impl(double v)
- {
- cutl_details_boost::uint32_t* ptr = (cutl_details_boost::uint32_t*)&v;
- std::size_t seed = *ptr++;
- hash_float_combine(seed, *ptr);
- return seed;
- }
-
- inline std::size_t float_hash_impl(long double v)
- {
- cutl_details_boost::uint32_t* ptr = (cutl_details_boost::uint32_t*)&v;
- std::size_t seed = *ptr++;
- hash_float_combine(seed, *ptr++);
- hash_float_combine(seed, *(cutl_details_boost::uint16_t*)ptr);
- return seed;
- }
- }
-}
-
-#endif
diff --git a/cutl/details/boost/functional/hash/extensions.hpp b/cutl/details/boost/functional/hash/extensions.hpp
index 2a3ae39..91771b4 100644
--- a/cutl/details/boost/functional/hash/extensions.hpp
+++ b/cutl/details/boost/functional/hash/extensions.hpp
@@ -15,6 +15,22 @@
#include <cutl/details/boost/functional/hash/hash.hpp>
#include <cutl/details/boost/detail/container_fwd.hpp>
+#include <cutl/details/boost/utility/enable_if.hpp>
+#include <cutl/details/boost/static_assert.hpp>
+#include <cutl/details/boost/preprocessor/repetition/repeat_from_to.hpp>
+#include <cutl/details/boost/preprocessor/repetition/enum_params.hpp>
+
+#if !defined(BOOST_NO_CXX11_HDR_ARRAY)
+# include <array>
+#endif
+
+#if !defined(BOOST_NO_CXX11_HDR_TUPLE)
+# include <tuple>
+#endif
+
+#if !defined(BOOST_NO_CXX11_HDR_MEMORY)
+# include <memory>
+#endif
#if defined(_MSC_VER) && (_MSC_VER >= 1020)
# pragma once
@@ -54,51 +70,51 @@ namespace cutl_details_boost
std::size_t hash_value(std::pair<A, B> const& v)
{
std::size_t seed = 0;
- hash_combine(seed, v.first);
- hash_combine(seed, v.second);
+ cutl_details_boost::hash_combine(seed, v.first);
+ cutl_details_boost::hash_combine(seed, v.second);
return seed;
}
template <class T, class A>
std::size_t hash_value(std::vector<T, A> const& v)
{
- return hash_range(v.begin(), v.end());
+ return cutl_details_boost::hash_range(v.begin(), v.end());
}
template <class T, class A>
std::size_t hash_value(std::list<T, A> const& v)
{
- return hash_range(v.begin(), v.end());
+ return cutl_details_boost::hash_range(v.begin(), v.end());
}
template <class T, class A>
std::size_t hash_value(std::deque<T, A> const& v)
{
- return hash_range(v.begin(), v.end());
+ return cutl_details_boost::hash_range(v.begin(), v.end());
}
template <class K, class C, class A>
std::size_t hash_value(std::set<K, C, A> const& v)
{
- return hash_range(v.begin(), v.end());
+ return cutl_details_boost::hash_range(v.begin(), v.end());
}
template <class K, class C, class A>
std::size_t hash_value(std::multiset<K, C, A> const& v)
{
- return hash_range(v.begin(), v.end());
+ return cutl_details_boost::hash_range(v.begin(), v.end());
}
template <class K, class T, class C, class A>
std::size_t hash_value(std::map<K, T, C, A> const& v)
{
- return hash_range(v.begin(), v.end());
+ return cutl_details_boost::hash_range(v.begin(), v.end());
}
template <class K, class T, class C, class A>
std::size_t hash_value(std::multimap<K, T, C, A> const& v)
{
- return hash_range(v.begin(), v.end());
+ return cutl_details_boost::hash_range(v.begin(), v.end());
}
template <class T>
@@ -110,6 +126,83 @@ namespace cutl_details_boost
return seed;
}
+#if !defined(BOOST_NO_CXX11_HDR_ARRAY)
+ template <class T, std::size_t N>
+ std::size_t hash_value(std::array<T, N> const& v)
+ {
+ return cutl_details_boost::hash_range(v.begin(), v.end());
+ }
+#endif
+
+#if !defined(BOOST_NO_CXX11_HDR_TUPLE)
+ namespace hash_detail {
+ template <std::size_t I, typename T>
+ inline typename cutl_details_boost::enable_if_c<(I == std::tuple_size<T>::value),
+ void>::type
+ hash_combine_tuple(std::size_t&, T const&)
+ {
+ }
+
+ template <std::size_t I, typename T>
+ inline typename cutl_details_boost::enable_if_c<(I < std::tuple_size<T>::value),
+ void>::type
+ hash_combine_tuple(std::size_t& seed, T const& v)
+ {
+ cutl_details_boost::hash_combine(seed, std::get<I>(v));
+ cutl_details_boost::hash_detail::hash_combine_tuple<I + 1>(seed, v);
+ }
+
+ template <typename T>
+ inline std::size_t hash_tuple(T const& v)
+ {
+ std::size_t seed = 0;
+ cutl_details_boost::hash_detail::hash_combine_tuple<0>(seed, v);
+ return seed;
+ }
+ }
+
+#if !defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES)
+ template <typename... T>
+ inline std::size_t hash_value(std::tuple<T...> const& v)
+ {
+ return cutl_details_boost::hash_detail::hash_tuple(v);
+ }
+#else
+
+ inline std::size_t hash_value(std::tuple<> const& v)
+ {
+ return cutl_details_boost::hash_detail::hash_tuple(v);
+ }
+
+# define BOOST_HASH_TUPLE_F(z, n, _) \
+ template< \
+ BOOST_PP_ENUM_PARAMS_Z(z, n, typename A) \
+ > \
+ inline std::size_t hash_value(std::tuple< \
+ BOOST_PP_ENUM_PARAMS_Z(z, n, A) \
+ > const& v) \
+ { \
+ return cutl_details_boost::hash_detail::hash_tuple(v); \
+ }
+
+ BOOST_PP_REPEAT_FROM_TO(1, 11, BOOST_HASH_TUPLE_F, _)
+# undef BOOST_HASH_TUPLE_F
+#endif
+
+#endif
+
+#if !defined(BOOST_NO_CXX11_SMART_PTR)
+ template <typename T>
+ inline std::size_t hash_value(std::shared_ptr<T> const& x) {
+ return cutl_details_boost::hash_value(x.get());
+ }
+
+ template <typename T, typename Deleter>
+ inline std::size_t hash_value(std::unique_ptr<T, Deleter> const& x) {
+ return cutl_details_boost::hash_value(x.get());
+ }
+#endif
+
//
// call_hash_impl
//
diff --git a/cutl/details/boost/functional/hash/hash.hpp b/cutl/details/boost/functional/hash/hash.hpp
index 3ea7bb5..cb4a869 100644
--- a/cutl/details/boost/functional/hash/hash.hpp
+++ b/cutl/details/boost/functional/hash/hash.hpp
@@ -15,16 +15,15 @@
#include <cutl/details/boost/functional/hash/detail/hash_float.hpp>
#include <string>
#include <cutl/details/boost/limits.hpp>
-
-#if defined(BOOST_HASH_NO_IMPLICIT_CASTS)
-#include <cutl/details/boost/static_assert.hpp>
-#endif
+#include <cutl/details/boost/type_traits/is_enum.hpp>
+#include <cutl/details/boost/type_traits/is_integral.hpp>
+#include <cutl/details/boost/utility/enable_if.hpp>
#if defined(BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION)
#include <cutl/details/boost/type_traits/is_pointer.hpp>
#endif
-#if !defined(BOOST_NO_0X_HDR_TYPEINDEX)
+#if !defined(BOOST_NO_CXX11_HDR_TYPEINDEX)
#include <typeindex>
#endif
@@ -37,38 +36,82 @@
namespace cutl_details_boost
{
-#if defined(BOOST_HASH_NO_IMPLICIT_CASTS)
-
- // If you get a static assertion here, it's because hash_value
- // isn't declared for your type.
- template <typename T>
- std::size_t hash_value(T const&) {
- BOOST_STATIC_ASSERT((T*) 0 && false);
- return 0;
- }
+ namespace hash_detail
+ {
+ struct enable_hash_value { typedef std::size_t type; };
+
+ template <typename T> struct basic_numbers {};
+ template <typename T> struct long_numbers;
+ template <typename T> struct ulong_numbers;
+ template <typename T> struct float_numbers {};
+
+ template <> struct basic_numbers<bool> :
+ cutl_details_boost::hash_detail::enable_hash_value {};
+ template <> struct basic_numbers<char> :
+ cutl_details_boost::hash_detail::enable_hash_value {};
+ template <> struct basic_numbers<unsigned char> :
+ cutl_details_boost::hash_detail::enable_hash_value {};
+ template <> struct basic_numbers<signed char> :
+ cutl_details_boost::hash_detail::enable_hash_value {};
+ template <> struct basic_numbers<short> :
+ cutl_details_boost::hash_detail::enable_hash_value {};
+ template <> struct basic_numbers<unsigned short> :
+ cutl_details_boost::hash_detail::enable_hash_value {};
+ template <> struct basic_numbers<int> :
+ cutl_details_boost::hash_detail::enable_hash_value {};
+ template <> struct basic_numbers<unsigned int> :
+ cutl_details_boost::hash_detail::enable_hash_value {};
+ template <> struct basic_numbers<long> :
+ cutl_details_boost::hash_detail::enable_hash_value {};
+ template <> struct basic_numbers<unsigned long> :
+ cutl_details_boost::hash_detail::enable_hash_value {};
+#if !defined(BOOST_NO_INTRINSIC_WCHAR_T)
+ template <> struct basic_numbers<wchar_t> :
+ cutl_details_boost::hash_detail::enable_hash_value {};
#endif
- std::size_t hash_value(bool);
- std::size_t hash_value(char);
- std::size_t hash_value(unsigned char);
- std::size_t hash_value(signed char);
- std::size_t hash_value(short);
- std::size_t hash_value(unsigned short);
- std::size_t hash_value(int);
- std::size_t hash_value(unsigned int);
- std::size_t hash_value(long);
- std::size_t hash_value(unsigned long);
+ // long_numbers is defined like this to allow for separate
+ // specialization for long_long and int128_type, in case
+ // they conflict.
+ template <typename T> struct long_numbers2 {};
+ template <typename T> struct ulong_numbers2 {};
+ template <typename T> struct long_numbers : long_numbers2<T> {};
+ template <typename T> struct ulong_numbers : ulong_numbers2<T> {};
-#if !defined(BOOST_NO_INTRINSIC_WCHAR_T)
- std::size_t hash_value(wchar_t);
-#endif
-
#if !defined(BOOST_NO_LONG_LONG)
- std::size_t hash_value(cutl_details_boost::long_long_type);
- std::size_t hash_value(cutl_details_boost::ulong_long_type);
+ template <> struct long_numbers<cutl_details_boost::long_long_type> :
+ cutl_details_boost::hash_detail::enable_hash_value {};
+ template <> struct ulong_numbers<cutl_details_boost::ulong_long_type> :
+ cutl_details_boost::hash_detail::enable_hash_value {};
#endif
+#if defined(BOOST_HAS_INT128)
+ template <> struct long_numbers2<cutl_details_boost::int128_type> :
+ cutl_details_boost::hash_detail::enable_hash_value {};
+ template <> struct ulong_numbers2<cutl_details_boost::uint128_type> :
+ cutl_details_boost::hash_detail::enable_hash_value {};
+#endif
+
+ template <> struct float_numbers<float> :
+ cutl_details_boost::hash_detail::enable_hash_value {};
+ template <> struct float_numbers<double> :
+ cutl_details_boost::hash_detail::enable_hash_value {};
+ template <> struct float_numbers<long double> :
+ cutl_details_boost::hash_detail::enable_hash_value {};
+ }
+
+ template <typename T>
+ typename cutl_details_boost::hash_detail::basic_numbers<T>::type hash_value(T);
+ template <typename T>
+ typename cutl_details_boost::hash_detail::long_numbers<T>::type hash_value(T);
+ template <typename T>
+ typename cutl_details_boost::hash_detail::ulong_numbers<T>::type hash_value(T);
+
+ template <typename T>
+ typename cutl_details_boost::enable_if<cutl_details_boost::is_enum<T>, std::size_t>::type
+ hash_value(T);
+
#if !BOOST_WORKAROUND(__DMC__, <= 0x848)
template <class T> std::size_t hash_value(T* const&);
#else
@@ -83,15 +126,14 @@ namespace cutl_details_boost
std::size_t hash_value(T (&x)[N]);
#endif
- std::size_t hash_value(float v);
- std::size_t hash_value(double v);
- std::size_t hash_value(long double v);
-
template <class Ch, class A>
std::size_t hash_value(
std::basic_string<Ch, std::BOOST_HASH_CHAR_TRAITS<Ch>, A> const&);
-#if !defined(BOOST_NO_0X_HDR_TYPEINDEX)
+ template <typename T>
+ typename cutl_details_boost::hash_detail::float_numbers<T>::type hash_value(T);
+
+#if !defined(BOOST_NO_CXX11_HDR_TYPEINDEX)
std::size_t hash_value(std::type_index);
#endif
@@ -141,74 +183,30 @@ namespace cutl_details_boost
}
}
- inline std::size_t hash_value(bool v)
- {
- return static_cast<std::size_t>(v);
- }
-
- inline std::size_t hash_value(char v)
- {
- return static_cast<std::size_t>(v);
- }
-
- inline std::size_t hash_value(unsigned char v)
- {
- return static_cast<std::size_t>(v);
- }
-
- inline std::size_t hash_value(signed char v)
- {
- return static_cast<std::size_t>(v);
- }
-
- inline std::size_t hash_value(short v)
- {
- return static_cast<std::size_t>(v);
- }
-
- inline std::size_t hash_value(unsigned short v)
- {
- return static_cast<std::size_t>(v);
- }
-
- inline std::size_t hash_value(int v)
- {
- return static_cast<std::size_t>(v);
- }
-
- inline std::size_t hash_value(unsigned int v)
+ template <typename T>
+ typename cutl_details_boost::hash_detail::basic_numbers<T>::type hash_value(T v)
{
return static_cast<std::size_t>(v);
}
- inline std::size_t hash_value(long v)
+ template <typename T>
+ typename cutl_details_boost::hash_detail::long_numbers<T>::type hash_value(T v)
{
- return static_cast<std::size_t>(v);
+ return hash_detail::hash_value_signed(v);
}
- inline std::size_t hash_value(unsigned long v)
+ template <typename T>
+ typename cutl_details_boost::hash_detail::ulong_numbers<T>::type hash_value(T v)
{
- return static_cast<std::size_t>(v);
+ return hash_detail::hash_value_unsigned(v);
}
-#if !defined(BOOST_NO_INTRINSIC_WCHAR_T)
- inline std::size_t hash_value(wchar_t v)
+ template <typename T>
+ typename cutl_details_boost::enable_if<cutl_details_boost::is_enum<T>, std::size_t>::type
+ hash_value(T v)
{
return static_cast<std::size_t>(v);
}
-#endif
-
-#if !defined(BOOST_NO_LONG_LONG)
- inline std::size_t hash_value(cutl_details_boost::long_long_type v)
- {
- return hash_detail::hash_value_signed(v);
- }
-
- inline std::size_t hash_value(cutl_details_boost::ulong_long_type v)
- {
- return hash_detail::hash_value_unsigned(v);
- }
-#endif
// Implementation by Alberto Barbati and Dave Harris.
#if !BOOST_WORKAROUND(__DMC__, <= 0x848)
@@ -324,22 +322,13 @@ namespace cutl_details_boost
return hash_range(v.begin(), v.end());
}
- inline std::size_t hash_value(float v)
- {
- return cutl_details_boost::hash_detail::float_hash_value(v);
- }
-
- inline std::size_t hash_value(double v)
- {
- return cutl_details_boost::hash_detail::float_hash_value(v);
- }
-
- inline std::size_t hash_value(long double v)
+ template <typename T>
+ typename cutl_details_boost::hash_detail::float_numbers<T>::type hash_value(T v)
{
return cutl_details_boost::hash_detail::float_hash_value(v);
}
-#if !defined(BOOST_NO_0X_HDR_TYPEINDEX)
+#if !defined(BOOST_NO_CXX11_HDR_TYPEINDEX)
inline std::size_t hash_value(std::type_index v)
{
return v.hash_code();
@@ -450,7 +439,12 @@ namespace cutl_details_boost
BOOST_HASH_SPECIALIZE(cutl_details_boost::ulong_long_type)
#endif
-#if !defined(BOOST_NO_0X_HDR_TYPEINDEX)
+#if defined(BOOST_HAS_INT128)
+ BOOST_HASH_SPECIALIZE(cutl_details_boost::int128_type)
+ BOOST_HASH_SPECIALIZE(cutl_details_boost::uint128_type)
+#endif
+
+#if !defined(BOOST_NO_CXX11_HDR_TYPEINDEX)
BOOST_HASH_SPECIALIZE(std::type_index)
#endif