forked from boostorg/container_hash
Merge branch 'develop'
- Support std::string_view, std::error_code, std::error_condition, std::optional, std::variant, std::monostate - Improved testing, added appveyor build file - Move headers from 'container_hash/hash' to 'container_hash', so there's not pointless nesting in the new directory layout
This commit is contained in:
33
.appveyor.yml
Normal file
33
.appveyor.yml
Normal file
@@ -0,0 +1,33 @@
|
||||
# Copyright 2017 Daniel James
|
||||
# Distributed under the Boost Software License, Version 1.0.
|
||||
# (See accompanying file LICENSE_1_0.txt or copy at http://boost.org/LICENSE_1_0.txt)
|
||||
|
||||
version: 1.0.{build}-{branch}
|
||||
|
||||
shallow_clone: true
|
||||
|
||||
environment:
|
||||
matrix:
|
||||
- APPVEYOR_BUILD_WORKER_IMAGE: Visual Studio 2013
|
||||
TOOLSET: msvc-10.0,msvc-11.0,msvc-12.0
|
||||
- APPVEYOR_BUILD_WORKER_IMAGE: Visual Studio 2015
|
||||
TOOLSET: msvc-14.0
|
||||
- APPVEYOR_BUILD_WORKER_IMAGE: Visual Studio 2017
|
||||
TOOLSET: msvc-14.1
|
||||
|
||||
install:
|
||||
- cd c:\projects
|
||||
- curl -sSL -o boost.7z https://dl.bintray.com/boostorg/release/1.66.0/source/boost_1_66_0.7z
|
||||
- 7z x boost.7z
|
||||
- set BOOST_ROOT=c:\projects\boost_1_66_0
|
||||
- rd /s /q %BOOST_ROOT%\boost\functional\hash
|
||||
- cd %BOOST_ROOT%\tools\build
|
||||
- cmd /c bootstrap
|
||||
- cd %APPVEYOR_BUILD_FOLDER%
|
||||
- echo. 2>Jamroot.jam
|
||||
|
||||
build: off
|
||||
|
||||
test_script:
|
||||
- cd %APPVEYOR_BUILD_FOLDER%\test
|
||||
- cmd /c %BOOST_ROOT%\tools\build\b2 -j 3 toolset=%TOOLSET% include=%APPVEYOR_BUILD_FOLDER%\include include=%BOOST_ROOT%
|
11
.travis.yml
11
.travis.yml
@@ -14,6 +14,16 @@ matrix:
|
||||
env: |
|
||||
USER_CONFIG="using gcc : : g++-4.8 -Werror ;"
|
||||
CXXSTD=03,11
|
||||
- compiler: g++-7
|
||||
env: |
|
||||
USER_CONFIG="using gcc : : g++-7 -Werror ;"
|
||||
CXXSTD=11,14,17
|
||||
addons:
|
||||
apt:
|
||||
packages:
|
||||
- g++-7
|
||||
sources:
|
||||
- ubuntu-toolchain-r-test
|
||||
- compiler: clang
|
||||
env: |
|
||||
USER_CONFIG="using clang : : clang++ -Werror ;"
|
||||
@@ -64,4 +74,5 @@ before_script:
|
||||
|
||||
script:
|
||||
- cd ${TRAVIS_BUILD_DIR}/test
|
||||
- ${HOME}/opt/bin/b2 --verbose-test -j 3 cxxstd=$CXXSTD -q ${BJAM_TOOLSET} include=${BOOST_ROOT} include=${TRAVIS_BUILD_DIR}/include hash_info
|
||||
- ${HOME}/opt/bin/b2 -j 3 cxxstd=$CXXSTD -q ${BJAM_TOOLSET} include=${BOOST_ROOT} include=${TRAVIS_BUILD_DIR}/include
|
||||
|
@@ -11,8 +11,8 @@
|
||||
#pragma once
|
||||
#endif
|
||||
|
||||
#include <boost/container_hash/hash/detail/float_functions.hpp>
|
||||
#include <boost/container_hash/hash/detail/limits.hpp>
|
||||
#include <boost/container_hash/detail/float_functions.hpp>
|
||||
#include <boost/container_hash/detail/limits.hpp>
|
||||
#include <boost/core/enable_if.hpp>
|
||||
#include <boost/integer/static_log2.hpp>
|
||||
#include <boost/cstdint.hpp>
|
@@ -18,7 +18,7 @@
|
||||
#pragma once
|
||||
#endif
|
||||
|
||||
#include <boost/container_hash/hash/hash.hpp>
|
||||
#include <boost/container_hash/hash.hpp>
|
||||
#include <boost/detail/container_fwd.hpp>
|
||||
#include <boost/core/enable_if.hpp>
|
||||
#include <boost/static_assert.hpp>
|
@@ -1,7 +1,761 @@
|
||||
|
||||
// Copyright 2005-2009 Daniel James.
|
||||
// Copyright 2005-2014 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)
|
||||
|
||||
#include <boost/container_hash/hash/hash.hpp>
|
||||
// Based on Peter Dimov's proposal
|
||||
// http://www.open-std.org/JTC1/SC22/WG21/docs/papers/2005/n1756.pdf
|
||||
// issue 6.18.
|
||||
//
|
||||
// This also contains public domain code from MurmurHash. From the
|
||||
// MurmurHash header:
|
||||
|
||||
// MurmurHash3 was written by Austin Appleby, and is placed in the public
|
||||
// domain. The author hereby disclaims copyright to this source code.
|
||||
|
||||
#if !defined(BOOST_FUNCTIONAL_HASH_HASH_HPP)
|
||||
#define BOOST_FUNCTIONAL_HASH_HASH_HPP
|
||||
|
||||
#include <boost/container_hash/hash_fwd.hpp>
|
||||
#include <functional>
|
||||
#include <boost/container_hash/detail/hash_float.hpp>
|
||||
#include <string>
|
||||
#include <boost/limits.hpp>
|
||||
#include <boost/type_traits/is_enum.hpp>
|
||||
#include <boost/type_traits/is_integral.hpp>
|
||||
#include <boost/core/enable_if.hpp>
|
||||
#include <boost/cstdint.hpp>
|
||||
|
||||
#if defined(BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION)
|
||||
#include <boost/type_traits/is_pointer.hpp>
|
||||
#endif
|
||||
|
||||
#if !defined(BOOST_NO_CXX11_HDR_TYPEINDEX)
|
||||
#include <typeindex>
|
||||
#endif
|
||||
|
||||
#if !defined(BOOST_NO_CXX11_HDR_SYSTEM_ERROR)
|
||||
#include <system_error>
|
||||
#endif
|
||||
|
||||
#if defined(BOOST_MSVC)
|
||||
#pragma warning(push)
|
||||
|
||||
#if BOOST_MSVC >= 1400
|
||||
#pragma warning(disable:6295) // Ill-defined for-loop : 'unsigned int' values
|
||||
// are always of range '0' to '4294967295'.
|
||||
// Loop executes infinitely.
|
||||
#endif
|
||||
|
||||
#endif
|
||||
|
||||
#if BOOST_WORKAROUND(__GNUC__, < 3) \
|
||||
&& !defined(__SGI_STL_PORT) && !defined(_STLPORT_VERSION)
|
||||
#define BOOST_HASH_CHAR_TRAITS string_char_traits
|
||||
#else
|
||||
#define BOOST_HASH_CHAR_TRAITS char_traits
|
||||
#endif
|
||||
|
||||
#if defined(_MSC_VER)
|
||||
# define BOOST_FUNCTIONAL_HASH_ROTL32(x, r) _rotl(x,r)
|
||||
#else
|
||||
# define BOOST_FUNCTIONAL_HASH_ROTL32(x, r) (x << r) | (x >> (32 - r))
|
||||
#endif
|
||||
|
||||
// Detect whether standard library has C++17 headers
|
||||
|
||||
#if !defined(BOOST_HASH_CXX17)
|
||||
# if defined(BOOST_MSVC)
|
||||
# if defined(_HAS_CXX17) && _HAS_CXX17
|
||||
# define BOOST_HASH_CXX17 1
|
||||
# endif
|
||||
# elif defined(__cplusplus) && __cplusplus >= 201703
|
||||
# define BOOST_HASH_CXX17 1
|
||||
# endif
|
||||
#endif
|
||||
|
||||
#if !defined(BOOST_HASH_CXX17)
|
||||
# define BOOST_HASH_CXX17 0
|
||||
#endif
|
||||
|
||||
#if BOOST_HASH_CXX17 && defined(__has_include)
|
||||
# if !defined(BOOST_HASH_HAS_STRING_VIEW) && __has_include(<string_view>)
|
||||
# define BOOST_HASH_HAS_STRING_VIEW 1
|
||||
# endif
|
||||
# if !defined(BOOST_HASH_HAS_OPTIONAL) && __has_include(<optional>)
|
||||
# define BOOST_HASH_HAS_OPTIONAL 1
|
||||
# endif
|
||||
# if !defined(BOOST_HASH_HAS_VARIANT) && __has_include(<variant>)
|
||||
# define BOOST_HASH_HAS_VARIANT 1
|
||||
# endif
|
||||
#endif
|
||||
|
||||
#if !defined(BOOST_HASH_HAS_STRING_VIEW)
|
||||
# define BOOST_HASH_HAS_STRING_VIEW 0
|
||||
#endif
|
||||
|
||||
#if !defined(BOOST_HASH_HAS_OPTIONAL)
|
||||
# define BOOST_HASH_HAS_OPTIONAL 0
|
||||
#endif
|
||||
|
||||
#if !defined(BOOST_HASH_HAS_VARIANT)
|
||||
# define BOOST_HASH_HAS_VARIANT 0
|
||||
#endif
|
||||
|
||||
#if BOOST_HASH_HAS_STRING_VIEW
|
||||
# include <string_view>
|
||||
#endif
|
||||
|
||||
#if BOOST_HASH_HAS_OPTIONAL
|
||||
# include <optional>
|
||||
#endif
|
||||
|
||||
#if BOOST_HASH_HAS_VARIANT
|
||||
# include <variant>
|
||||
#endif
|
||||
|
||||
namespace boost
|
||||
{
|
||||
namespace hash_detail
|
||||
{
|
||||
#if defined(_HAS_AUTO_PTR_ETC) && !_HAS_AUTO_PTR_ETC
|
||||
template <typename T>
|
||||
struct hash_base
|
||||
{
|
||||
typedef T argument_type;
|
||||
typedef std::size_t result_type;
|
||||
};
|
||||
#else
|
||||
template <typename T>
|
||||
struct hash_base : std::unary_function<T, std::size_t> {};
|
||||
#endif
|
||||
|
||||
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> :
|
||||
boost::hash_detail::enable_hash_value {};
|
||||
template <> struct basic_numbers<char> :
|
||||
boost::hash_detail::enable_hash_value {};
|
||||
template <> struct basic_numbers<unsigned char> :
|
||||
boost::hash_detail::enable_hash_value {};
|
||||
template <> struct basic_numbers<signed char> :
|
||||
boost::hash_detail::enable_hash_value {};
|
||||
template <> struct basic_numbers<short> :
|
||||
boost::hash_detail::enable_hash_value {};
|
||||
template <> struct basic_numbers<unsigned short> :
|
||||
boost::hash_detail::enable_hash_value {};
|
||||
template <> struct basic_numbers<int> :
|
||||
boost::hash_detail::enable_hash_value {};
|
||||
template <> struct basic_numbers<unsigned int> :
|
||||
boost::hash_detail::enable_hash_value {};
|
||||
template <> struct basic_numbers<long> :
|
||||
boost::hash_detail::enable_hash_value {};
|
||||
template <> struct basic_numbers<unsigned long> :
|
||||
boost::hash_detail::enable_hash_value {};
|
||||
|
||||
#if !defined(BOOST_NO_INTRINSIC_WCHAR_T)
|
||||
template <> struct basic_numbers<wchar_t> :
|
||||
boost::hash_detail::enable_hash_value {};
|
||||
#endif
|
||||
|
||||
#if !defined(BOOST_NO_CXX11_CHAR16_T)
|
||||
template <> struct basic_numbers<char16_t> :
|
||||
boost::hash_detail::enable_hash_value {};
|
||||
#endif
|
||||
|
||||
#if !defined(BOOST_NO_CXX11_CHAR32_T)
|
||||
template <> struct basic_numbers<char32_t> :
|
||||
boost::hash_detail::enable_hash_value {};
|
||||
#endif
|
||||
|
||||
// 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_LONG_LONG)
|
||||
template <> struct long_numbers<boost::long_long_type> :
|
||||
boost::hash_detail::enable_hash_value {};
|
||||
template <> struct ulong_numbers<boost::ulong_long_type> :
|
||||
boost::hash_detail::enable_hash_value {};
|
||||
#endif
|
||||
|
||||
#if defined(BOOST_HAS_INT128)
|
||||
template <> struct long_numbers2<boost::int128_type> :
|
||||
boost::hash_detail::enable_hash_value {};
|
||||
template <> struct ulong_numbers2<boost::uint128_type> :
|
||||
boost::hash_detail::enable_hash_value {};
|
||||
#endif
|
||||
|
||||
template <> struct float_numbers<float> :
|
||||
boost::hash_detail::enable_hash_value {};
|
||||
template <> struct float_numbers<double> :
|
||||
boost::hash_detail::enable_hash_value {};
|
||||
template <> struct float_numbers<long double> :
|
||||
boost::hash_detail::enable_hash_value {};
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
typename boost::hash_detail::basic_numbers<T>::type hash_value(T);
|
||||
template <typename T>
|
||||
typename boost::hash_detail::long_numbers<T>::type hash_value(T);
|
||||
template <typename T>
|
||||
typename boost::hash_detail::ulong_numbers<T>::type hash_value(T);
|
||||
|
||||
template <typename T>
|
||||
typename boost::enable_if<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
|
||||
template <class T> std::size_t hash_value(T*);
|
||||
#endif
|
||||
|
||||
#if !defined(BOOST_NO_FUNCTION_TEMPLATE_ORDERING)
|
||||
template< class T, unsigned N >
|
||||
std::size_t hash_value(const T (&x)[N]);
|
||||
|
||||
template< class T, unsigned N >
|
||||
std::size_t hash_value(T (&x)[N]);
|
||||
#endif
|
||||
|
||||
template <class Ch, class A>
|
||||
std::size_t hash_value(
|
||||
std::basic_string<Ch, std::BOOST_HASH_CHAR_TRAITS<Ch>, A> const&);
|
||||
|
||||
#if BOOST_HASH_HAS_STRING_VIEW
|
||||
template <class Ch>
|
||||
std::size_t hash_value(
|
||||
std::basic_string_view<Ch, std::BOOST_HASH_CHAR_TRAITS<Ch> > const&);
|
||||
#endif
|
||||
|
||||
template <typename T>
|
||||
typename boost::hash_detail::float_numbers<T>::type hash_value(T);
|
||||
|
||||
#if BOOST_HASH_HAS_OPTIONAL
|
||||
template <typename T>
|
||||
std::size_t hash_value(std::optional<T> const&);
|
||||
#endif
|
||||
|
||||
#if BOOST_HASH_HAS_VARIANT
|
||||
std::size_t hash_value(std::monostate);
|
||||
template <typename... Types>
|
||||
std::size_t hash_value(std::variant<Types...> const&);
|
||||
#endif
|
||||
|
||||
#if !defined(BOOST_NO_CXX11_HDR_TYPEINDEX)
|
||||
std::size_t hash_value(std::type_index);
|
||||
#endif
|
||||
|
||||
#if !defined(BOOST_NO_CXX11_HDR_SYSTEM_ERROR)
|
||||
std::size_t hash_value(std::error_code const&);
|
||||
std::size_t hash_value(std::error_condition const&);
|
||||
#endif
|
||||
|
||||
// Implementation
|
||||
|
||||
namespace hash_detail
|
||||
{
|
||||
template <class T>
|
||||
inline std::size_t hash_value_signed(T val)
|
||||
{
|
||||
const unsigned int size_t_bits = std::numeric_limits<std::size_t>::digits;
|
||||
// ceiling(std::numeric_limits<T>::digits / size_t_bits) - 1
|
||||
const int length = (std::numeric_limits<T>::digits - 1)
|
||||
/ static_cast<int>(size_t_bits);
|
||||
|
||||
std::size_t seed = 0;
|
||||
T positive = val < 0 ? -1 - val : val;
|
||||
|
||||
// Hopefully, this loop can be unrolled.
|
||||
for(unsigned int i = length * size_t_bits; i > 0; i -= size_t_bits)
|
||||
{
|
||||
seed ^= (std::size_t) (positive >> i) + (seed<<6) + (seed>>2);
|
||||
}
|
||||
seed ^= (std::size_t) val + (seed<<6) + (seed>>2);
|
||||
|
||||
return seed;
|
||||
}
|
||||
|
||||
template <class T>
|
||||
inline std::size_t hash_value_unsigned(T val)
|
||||
{
|
||||
const unsigned int size_t_bits = std::numeric_limits<std::size_t>::digits;
|
||||
// ceiling(std::numeric_limits<T>::digits / size_t_bits) - 1
|
||||
const int length = (std::numeric_limits<T>::digits - 1)
|
||||
/ static_cast<int>(size_t_bits);
|
||||
|
||||
std::size_t seed = 0;
|
||||
|
||||
// Hopefully, this loop can be unrolled.
|
||||
for(unsigned int i = length * size_t_bits; i > 0; i -= size_t_bits)
|
||||
{
|
||||
seed ^= (std::size_t) (val >> i) + (seed<<6) + (seed>>2);
|
||||
}
|
||||
seed ^= (std::size_t) val + (seed<<6) + (seed>>2);
|
||||
|
||||
return seed;
|
||||
}
|
||||
|
||||
template <typename SizeT>
|
||||
inline void hash_combine_impl(SizeT& seed, SizeT value)
|
||||
{
|
||||
seed ^= value + 0x9e3779b9 + (seed<<6) + (seed>>2);
|
||||
}
|
||||
|
||||
inline void hash_combine_impl(boost::uint32_t& h1,
|
||||
boost::uint32_t k1)
|
||||
{
|
||||
const uint32_t c1 = 0xcc9e2d51;
|
||||
const uint32_t c2 = 0x1b873593;
|
||||
|
||||
k1 *= c1;
|
||||
k1 = BOOST_FUNCTIONAL_HASH_ROTL32(k1,15);
|
||||
k1 *= c2;
|
||||
|
||||
h1 ^= k1;
|
||||
h1 = BOOST_FUNCTIONAL_HASH_ROTL32(h1,13);
|
||||
h1 = h1*5+0xe6546b64;
|
||||
}
|
||||
|
||||
|
||||
// Don't define 64-bit hash combine on platforms without 64 bit integers,
|
||||
// and also not for 32-bit gcc as it warns about the 64-bit constant.
|
||||
#if !defined(BOOST_NO_INT64_T) && \
|
||||
!(defined(__GNUC__) && ULONG_MAX == 0xffffffff)
|
||||
|
||||
inline void hash_combine_impl(boost::uint64_t& h,
|
||||
boost::uint64_t k)
|
||||
{
|
||||
const boost::uint64_t m = UINT64_C(0xc6a4a7935bd1e995);
|
||||
const int r = 47;
|
||||
|
||||
k *= m;
|
||||
k ^= k >> r;
|
||||
k *= m;
|
||||
|
||||
h ^= k;
|
||||
h *= m;
|
||||
|
||||
// Completely arbitrary number, to prevent 0's
|
||||
// from hashing to 0.
|
||||
h += 0xe6546b64;
|
||||
}
|
||||
|
||||
#endif // BOOST_NO_INT64_T
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
typename boost::hash_detail::basic_numbers<T>::type hash_value(T v)
|
||||
{
|
||||
return static_cast<std::size_t>(v);
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
typename boost::hash_detail::long_numbers<T>::type hash_value(T v)
|
||||
{
|
||||
return hash_detail::hash_value_signed(v);
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
typename boost::hash_detail::ulong_numbers<T>::type hash_value(T v)
|
||||
{
|
||||
return hash_detail::hash_value_unsigned(v);
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
typename boost::enable_if<boost::is_enum<T>, std::size_t>::type
|
||||
hash_value(T v)
|
||||
{
|
||||
return static_cast<std::size_t>(v);
|
||||
}
|
||||
|
||||
// Implementation by Alberto Barbati and Dave Harris.
|
||||
#if !BOOST_WORKAROUND(__DMC__, <= 0x848)
|
||||
template <class T> std::size_t hash_value(T* const& v)
|
||||
#else
|
||||
template <class T> std::size_t hash_value(T* v)
|
||||
#endif
|
||||
{
|
||||
#if defined(__VMS) && __INITIAL_POINTER_SIZE == 64
|
||||
// for some reason ptrdiff_t on OpenVMS compiler with
|
||||
// 64 bit is not 64 bit !!!
|
||||
std::size_t x = static_cast<std::size_t>(
|
||||
reinterpret_cast<long long int>(v));
|
||||
#else
|
||||
std::size_t x = static_cast<std::size_t>(
|
||||
reinterpret_cast<std::ptrdiff_t>(v));
|
||||
#endif
|
||||
return x + (x >> 3);
|
||||
}
|
||||
|
||||
#if defined(BOOST_MSVC)
|
||||
#pragma warning(push)
|
||||
#if BOOST_MSVC <= 1400
|
||||
#pragma warning(disable:4267) // 'argument' : conversion from 'size_t' to
|
||||
// 'unsigned int', possible loss of data
|
||||
// A misguided attempt to detect 64-bit
|
||||
// incompatability.
|
||||
#endif
|
||||
#endif
|
||||
|
||||
template <class T>
|
||||
inline void hash_combine(std::size_t& seed, T const& v)
|
||||
{
|
||||
boost::hash<T> hasher;
|
||||
return boost::hash_detail::hash_combine_impl(seed, hasher(v));
|
||||
}
|
||||
|
||||
#if defined(BOOST_MSVC)
|
||||
#pragma warning(pop)
|
||||
#endif
|
||||
|
||||
template <class It>
|
||||
inline std::size_t hash_range(It first, It last)
|
||||
{
|
||||
std::size_t seed = 0;
|
||||
|
||||
for(; first != last; ++first)
|
||||
{
|
||||
hash_combine(seed, *first);
|
||||
}
|
||||
|
||||
return seed;
|
||||
}
|
||||
|
||||
template <class It>
|
||||
inline void hash_range(std::size_t& seed, It first, It last)
|
||||
{
|
||||
for(; first != last; ++first)
|
||||
{
|
||||
hash_combine(seed, *first);
|
||||
}
|
||||
}
|
||||
|
||||
#if BOOST_WORKAROUND(__BORLANDC__, BOOST_TESTED_AT(0x551))
|
||||
template <class T>
|
||||
inline std::size_t hash_range(T* first, T* last)
|
||||
{
|
||||
std::size_t seed = 0;
|
||||
|
||||
for(; first != last; ++first)
|
||||
{
|
||||
boost::hash<T> hasher;
|
||||
seed ^= hasher(*first) + 0x9e3779b9 + (seed<<6) + (seed>>2);
|
||||
}
|
||||
|
||||
return seed;
|
||||
}
|
||||
|
||||
template <class T>
|
||||
inline void hash_range(std::size_t& seed, T* first, T* last)
|
||||
{
|
||||
for(; first != last; ++first)
|
||||
{
|
||||
boost::hash<T> hasher;
|
||||
seed ^= hasher(*first) + 0x9e3779b9 + (seed<<6) + (seed>>2);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
#if !defined(BOOST_NO_FUNCTION_TEMPLATE_ORDERING)
|
||||
template< class T, unsigned N >
|
||||
inline std::size_t hash_value(const T (&x)[N])
|
||||
{
|
||||
return hash_range(x, x + N);
|
||||
}
|
||||
|
||||
template< class T, unsigned N >
|
||||
inline std::size_t hash_value(T (&x)[N])
|
||||
{
|
||||
return hash_range(x, x + N);
|
||||
}
|
||||
#endif
|
||||
|
||||
template <class Ch, class A>
|
||||
inline std::size_t hash_value(
|
||||
std::basic_string<Ch, std::BOOST_HASH_CHAR_TRAITS<Ch>, A> const& v)
|
||||
{
|
||||
return hash_range(v.begin(), v.end());
|
||||
}
|
||||
|
||||
#if BOOST_HASH_HAS_STRING_VIEW
|
||||
template <class Ch>
|
||||
inline std::size_t hash_value(
|
||||
std::basic_string_view<Ch, std::BOOST_HASH_CHAR_TRAITS<Ch> > const& v)
|
||||
{
|
||||
return hash_range(v.begin(), v.end());
|
||||
}
|
||||
#endif
|
||||
|
||||
template <typename T>
|
||||
typename boost::hash_detail::float_numbers<T>::type hash_value(T v)
|
||||
{
|
||||
return boost::hash_detail::float_hash_value(v);
|
||||
}
|
||||
|
||||
#if BOOST_HASH_HAS_OPTIONAL
|
||||
template <typename T>
|
||||
inline std::size_t hash_value(std::optional<T> const& v) {
|
||||
if (!v) {
|
||||
// Arbitray value for empty optional.
|
||||
return 0x12345678;
|
||||
} else {
|
||||
boost::hash<T> hf;
|
||||
return hf(*v);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
#if BOOST_HASH_HAS_VARIANT
|
||||
inline std::size_t hash_value(std::monostate) {
|
||||
return 0x87654321;
|
||||
}
|
||||
|
||||
template <typename... Types>
|
||||
inline std::size_t hash_value(std::variant<Types...> const& v) {
|
||||
std::size_t seed = 0;
|
||||
hash_combine(seed, v.index());
|
||||
std::visit([&seed](auto&& x) { hash_combine(seed, x); }, v);
|
||||
return seed;
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
#if !defined(BOOST_NO_CXX11_HDR_TYPEINDEX)
|
||||
inline std::size_t hash_value(std::type_index v)
|
||||
{
|
||||
return v.hash_code();
|
||||
}
|
||||
#endif
|
||||
|
||||
#if !defined(BOOST_NO_CXX11_HDR_SYSTEM_ERROR)
|
||||
inline std::size_t hash_value(std::error_code const& v) {
|
||||
std::size_t seed = 0;
|
||||
hash_combine(seed, v.value());
|
||||
hash_combine(seed, &v.category());
|
||||
return seed;
|
||||
}
|
||||
|
||||
inline std::size_t hash_value(std::error_condition const& v) {
|
||||
std::size_t seed = 0;
|
||||
hash_combine(seed, v.value());
|
||||
hash_combine(seed, &v.category());
|
||||
return seed;
|
||||
}
|
||||
#endif
|
||||
|
||||
//
|
||||
// boost::hash
|
||||
//
|
||||
|
||||
// Define the specializations required by the standard. The general purpose
|
||||
// boost::hash is defined later in extensions.hpp if
|
||||
// BOOST_HASH_NO_EXTENSIONS is not defined.
|
||||
|
||||
// BOOST_HASH_SPECIALIZE - define a specialization for a type which is
|
||||
// passed by copy.
|
||||
//
|
||||
// BOOST_HASH_SPECIALIZE_REF - define a specialization for a type which is
|
||||
// passed by const reference.
|
||||
//
|
||||
// These are undefined later.
|
||||
|
||||
#define BOOST_HASH_SPECIALIZE(type) \
|
||||
template <> struct hash<type> \
|
||||
: public boost::hash_detail::hash_base<type> \
|
||||
{ \
|
||||
std::size_t operator()(type v) const \
|
||||
{ \
|
||||
return boost::hash_value(v); \
|
||||
} \
|
||||
};
|
||||
|
||||
#define BOOST_HASH_SPECIALIZE_REF(type) \
|
||||
template <> struct hash<type> \
|
||||
: public boost::hash_detail::hash_base<type> \
|
||||
{ \
|
||||
std::size_t operator()(type const& v) const \
|
||||
{ \
|
||||
return boost::hash_value(v); \
|
||||
} \
|
||||
};
|
||||
|
||||
#define BOOST_HASH_SPECIALIZE_TEMPLATE_REF(type) \
|
||||
struct hash<type> \
|
||||
: public boost::hash_detail::hash_base<type> \
|
||||
{ \
|
||||
std::size_t operator()(type const& v) const \
|
||||
{ \
|
||||
return boost::hash_value(v); \
|
||||
} \
|
||||
};
|
||||
|
||||
BOOST_HASH_SPECIALIZE(bool)
|
||||
BOOST_HASH_SPECIALIZE(char)
|
||||
BOOST_HASH_SPECIALIZE(signed char)
|
||||
BOOST_HASH_SPECIALIZE(unsigned char)
|
||||
#if !defined(BOOST_NO_INTRINSIC_WCHAR_T)
|
||||
BOOST_HASH_SPECIALIZE(wchar_t)
|
||||
#endif
|
||||
#if !defined(BOOST_NO_CXX11_CHAR16_T)
|
||||
BOOST_HASH_SPECIALIZE(char16_t)
|
||||
#endif
|
||||
#if !defined(BOOST_NO_CXX11_CHAR32_T)
|
||||
BOOST_HASH_SPECIALIZE(char32_t)
|
||||
#endif
|
||||
BOOST_HASH_SPECIALIZE(short)
|
||||
BOOST_HASH_SPECIALIZE(unsigned short)
|
||||
BOOST_HASH_SPECIALIZE(int)
|
||||
BOOST_HASH_SPECIALIZE(unsigned int)
|
||||
BOOST_HASH_SPECIALIZE(long)
|
||||
BOOST_HASH_SPECIALIZE(unsigned long)
|
||||
|
||||
BOOST_HASH_SPECIALIZE(float)
|
||||
BOOST_HASH_SPECIALIZE(double)
|
||||
BOOST_HASH_SPECIALIZE(long double)
|
||||
|
||||
BOOST_HASH_SPECIALIZE_REF(std::string)
|
||||
#if !defined(BOOST_NO_STD_WSTRING) && !defined(BOOST_NO_INTRINSIC_WCHAR_T)
|
||||
BOOST_HASH_SPECIALIZE_REF(std::wstring)
|
||||
#endif
|
||||
#if !defined(BOOST_NO_CXX11_CHAR16_T)
|
||||
BOOST_HASH_SPECIALIZE_REF(std::basic_string<char16_t>)
|
||||
#endif
|
||||
#if !defined(BOOST_NO_CXX11_CHAR32_T)
|
||||
BOOST_HASH_SPECIALIZE_REF(std::basic_string<char32_t>)
|
||||
#endif
|
||||
|
||||
#if BOOST_HASH_HAS_STRING_VIEW
|
||||
BOOST_HASH_SPECIALIZE_REF(std::string_view)
|
||||
# if !defined(BOOST_NO_STD_WSTRING) && !defined(BOOST_NO_INTRINSIC_WCHAR_T)
|
||||
BOOST_HASH_SPECIALIZE_REF(std::wstring_view)
|
||||
# endif
|
||||
# if !defined(BOOST_NO_CXX11_CHAR16_T)
|
||||
BOOST_HASH_SPECIALIZE_REF(std::basic_string_view<char16_t>)
|
||||
# endif
|
||||
# if !defined(BOOST_NO_CXX11_CHAR32_T)
|
||||
BOOST_HASH_SPECIALIZE_REF(std::basic_string_view<char32_t>)
|
||||
# endif
|
||||
#endif
|
||||
|
||||
#if !defined(BOOST_NO_LONG_LONG)
|
||||
BOOST_HASH_SPECIALIZE(boost::long_long_type)
|
||||
BOOST_HASH_SPECIALIZE(boost::ulong_long_type)
|
||||
#endif
|
||||
|
||||
#if defined(BOOST_HAS_INT128)
|
||||
BOOST_HASH_SPECIALIZE(boost::int128_type)
|
||||
BOOST_HASH_SPECIALIZE(boost::uint128_type)
|
||||
#endif
|
||||
|
||||
#if BOOST_HASH_HAS_OPTIONAL
|
||||
template <typename T>
|
||||
BOOST_HASH_SPECIALIZE_TEMPLATE_REF(std::optional<T>)
|
||||
#endif
|
||||
|
||||
#if !defined(BOOST_HASH_HAS_VARIANT)
|
||||
template <typename... T>
|
||||
BOOST_HASH_SPECIALIZE_TEMPLATE_REF(std::variant<T...>)
|
||||
BOOST_HASH_SPECIALIZE(std::monostate)
|
||||
#endif
|
||||
|
||||
#if !defined(BOOST_NO_CXX11_HDR_TYPEINDEX)
|
||||
BOOST_HASH_SPECIALIZE(std::type_index)
|
||||
#endif
|
||||
|
||||
#undef BOOST_HASH_SPECIALIZE
|
||||
#undef BOOST_HASH_SPECIALIZE_REF
|
||||
#undef BOOST_HASH_SPECIALIZE_TEMPLATE_REF
|
||||
|
||||
// Specializing boost::hash for pointers.
|
||||
|
||||
#if !defined(BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION)
|
||||
|
||||
template <class T>
|
||||
struct hash<T*>
|
||||
: public boost::hash_detail::hash_base<T*>
|
||||
{
|
||||
std::size_t operator()(T* v) const
|
||||
{
|
||||
#if !BOOST_WORKAROUND(__SUNPRO_CC, <= 0x590)
|
||||
return boost::hash_value(v);
|
||||
#else
|
||||
std::size_t x = static_cast<std::size_t>(
|
||||
reinterpret_cast<std::ptrdiff_t>(v));
|
||||
|
||||
return x + (x >> 3);
|
||||
#endif
|
||||
}
|
||||
};
|
||||
|
||||
#else
|
||||
|
||||
// For compilers without partial specialization, we define a
|
||||
// boost::hash for all remaining types. But hash_impl is only defined
|
||||
// for pointers in 'extensions.hpp' - so when BOOST_HASH_NO_EXTENSIONS
|
||||
// is defined there will still be a compile error for types not supported
|
||||
// in the standard.
|
||||
|
||||
namespace hash_detail
|
||||
{
|
||||
template <bool IsPointer>
|
||||
struct hash_impl;
|
||||
|
||||
template <>
|
||||
struct hash_impl<true>
|
||||
{
|
||||
template <class T>
|
||||
struct inner
|
||||
: public boost::hash_detail::hash_base<T>
|
||||
{
|
||||
std::size_t operator()(T val) const
|
||||
{
|
||||
#if !BOOST_WORKAROUND(__SUNPRO_CC, <= 590)
|
||||
return boost::hash_value(val);
|
||||
#else
|
||||
std::size_t x = static_cast<std::size_t>(
|
||||
reinterpret_cast<std::ptrdiff_t>(val));
|
||||
|
||||
return x + (x >> 3);
|
||||
#endif
|
||||
}
|
||||
};
|
||||
};
|
||||
}
|
||||
|
||||
template <class T> struct hash
|
||||
: public boost::hash_detail::hash_impl<boost::is_pointer<T>::value>
|
||||
::BOOST_NESTED_TEMPLATE inner<T>
|
||||
{
|
||||
};
|
||||
|
||||
#endif
|
||||
}
|
||||
|
||||
#undef BOOST_HASH_CHAR_TRAITS
|
||||
#undef BOOST_FUNCTIONAL_HASH_ROTL32
|
||||
|
||||
#if defined(BOOST_MSVC)
|
||||
#pragma warning(pop)
|
||||
#endif
|
||||
|
||||
#endif // BOOST_FUNCTIONAL_HASH_HASH_HPP
|
||||
|
||||
// Include this outside of the include guards in case the file is included
|
||||
// twice - once with BOOST_HASH_NO_EXTENSIONS defined, and then with it
|
||||
// undefined.
|
||||
|
||||
#if !defined(BOOST_HASH_NO_EXTENSIONS) \
|
||||
&& !defined(BOOST_FUNCTIONAL_HASH_EXTENSIONS_HPP)
|
||||
#include <boost/container_hash/extensions.hpp>
|
||||
#endif
|
||||
|
@@ -1,595 +0,0 @@
|
||||
|
||||
// Copyright 2005-2014 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)
|
||||
|
||||
// Based on Peter Dimov's proposal
|
||||
// http://www.open-std.org/JTC1/SC22/WG21/docs/papers/2005/n1756.pdf
|
||||
// issue 6.18.
|
||||
//
|
||||
// This also contains public domain code from MurmurHash. From the
|
||||
// MurmurHash header:
|
||||
|
||||
// MurmurHash3 was written by Austin Appleby, and is placed in the public
|
||||
// domain. The author hereby disclaims copyright to this source code.
|
||||
|
||||
#if !defined(BOOST_FUNCTIONAL_HASH_HASH_HPP)
|
||||
#define BOOST_FUNCTIONAL_HASH_HASH_HPP
|
||||
|
||||
#include <boost/container_hash/hash/hash_fwd.hpp>
|
||||
#include <functional>
|
||||
#include <boost/container_hash/hash/detail/hash_float.hpp>
|
||||
#include <string>
|
||||
#include <boost/limits.hpp>
|
||||
#include <boost/type_traits/is_enum.hpp>
|
||||
#include <boost/type_traits/is_integral.hpp>
|
||||
#include <boost/core/enable_if.hpp>
|
||||
#include <boost/cstdint.hpp>
|
||||
|
||||
#if defined(BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION)
|
||||
#include <boost/type_traits/is_pointer.hpp>
|
||||
#endif
|
||||
|
||||
#if !defined(BOOST_NO_CXX11_HDR_TYPEINDEX)
|
||||
#include <typeindex>
|
||||
#endif
|
||||
|
||||
#if defined(BOOST_MSVC)
|
||||
#pragma warning(push)
|
||||
|
||||
#if BOOST_MSVC >= 1400
|
||||
#pragma warning(disable:6295) // Ill-defined for-loop : 'unsigned int' values
|
||||
// are always of range '0' to '4294967295'.
|
||||
// Loop executes infinitely.
|
||||
#endif
|
||||
|
||||
#endif
|
||||
|
||||
#if BOOST_WORKAROUND(__GNUC__, < 3) \
|
||||
&& !defined(__SGI_STL_PORT) && !defined(_STLPORT_VERSION)
|
||||
#define BOOST_HASH_CHAR_TRAITS string_char_traits
|
||||
#else
|
||||
#define BOOST_HASH_CHAR_TRAITS char_traits
|
||||
#endif
|
||||
|
||||
#if defined(_MSC_VER)
|
||||
# define BOOST_FUNCTIONAL_HASH_ROTL32(x, r) _rotl(x,r)
|
||||
#else
|
||||
# define BOOST_FUNCTIONAL_HASH_ROTL32(x, r) (x << r) | (x >> (32 - r))
|
||||
#endif
|
||||
|
||||
namespace boost
|
||||
{
|
||||
namespace hash_detail
|
||||
{
|
||||
#if defined(_HAS_AUTO_PTR_ETC) && !_HAS_AUTO_PTR_ETC
|
||||
template <typename T>
|
||||
struct hash_base
|
||||
{
|
||||
typedef T argument_type;
|
||||
typedef std::size_t result_type;
|
||||
};
|
||||
#else
|
||||
template <typename T>
|
||||
struct hash_base : std::unary_function<T, std::size_t> {};
|
||||
#endif
|
||||
|
||||
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> :
|
||||
boost::hash_detail::enable_hash_value {};
|
||||
template <> struct basic_numbers<char> :
|
||||
boost::hash_detail::enable_hash_value {};
|
||||
template <> struct basic_numbers<unsigned char> :
|
||||
boost::hash_detail::enable_hash_value {};
|
||||
template <> struct basic_numbers<signed char> :
|
||||
boost::hash_detail::enable_hash_value {};
|
||||
template <> struct basic_numbers<short> :
|
||||
boost::hash_detail::enable_hash_value {};
|
||||
template <> struct basic_numbers<unsigned short> :
|
||||
boost::hash_detail::enable_hash_value {};
|
||||
template <> struct basic_numbers<int> :
|
||||
boost::hash_detail::enable_hash_value {};
|
||||
template <> struct basic_numbers<unsigned int> :
|
||||
boost::hash_detail::enable_hash_value {};
|
||||
template <> struct basic_numbers<long> :
|
||||
boost::hash_detail::enable_hash_value {};
|
||||
template <> struct basic_numbers<unsigned long> :
|
||||
boost::hash_detail::enable_hash_value {};
|
||||
|
||||
#if !defined(BOOST_NO_INTRINSIC_WCHAR_T)
|
||||
template <> struct basic_numbers<wchar_t> :
|
||||
boost::hash_detail::enable_hash_value {};
|
||||
#endif
|
||||
|
||||
#if !defined(BOOST_NO_CXX11_CHAR16_T)
|
||||
template <> struct basic_numbers<char16_t> :
|
||||
boost::hash_detail::enable_hash_value {};
|
||||
#endif
|
||||
|
||||
#if !defined(BOOST_NO_CXX11_CHAR32_T)
|
||||
template <> struct basic_numbers<char32_t> :
|
||||
boost::hash_detail::enable_hash_value {};
|
||||
#endif
|
||||
|
||||
// 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_LONG_LONG)
|
||||
template <> struct long_numbers<boost::long_long_type> :
|
||||
boost::hash_detail::enable_hash_value {};
|
||||
template <> struct ulong_numbers<boost::ulong_long_type> :
|
||||
boost::hash_detail::enable_hash_value {};
|
||||
#endif
|
||||
|
||||
#if defined(BOOST_HAS_INT128)
|
||||
template <> struct long_numbers2<boost::int128_type> :
|
||||
boost::hash_detail::enable_hash_value {};
|
||||
template <> struct ulong_numbers2<boost::uint128_type> :
|
||||
boost::hash_detail::enable_hash_value {};
|
||||
#endif
|
||||
|
||||
template <> struct float_numbers<float> :
|
||||
boost::hash_detail::enable_hash_value {};
|
||||
template <> struct float_numbers<double> :
|
||||
boost::hash_detail::enable_hash_value {};
|
||||
template <> struct float_numbers<long double> :
|
||||
boost::hash_detail::enable_hash_value {};
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
typename boost::hash_detail::basic_numbers<T>::type hash_value(T);
|
||||
template <typename T>
|
||||
typename boost::hash_detail::long_numbers<T>::type hash_value(T);
|
||||
template <typename T>
|
||||
typename boost::hash_detail::ulong_numbers<T>::type hash_value(T);
|
||||
|
||||
template <typename T>
|
||||
typename boost::enable_if<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
|
||||
template <class T> std::size_t hash_value(T*);
|
||||
#endif
|
||||
|
||||
#if !defined(BOOST_NO_FUNCTION_TEMPLATE_ORDERING)
|
||||
template< class T, unsigned N >
|
||||
std::size_t hash_value(const T (&x)[N]);
|
||||
|
||||
template< class T, unsigned N >
|
||||
std::size_t hash_value(T (&x)[N]);
|
||||
#endif
|
||||
|
||||
template <class Ch, class A>
|
||||
std::size_t hash_value(
|
||||
std::basic_string<Ch, std::BOOST_HASH_CHAR_TRAITS<Ch>, A> const&);
|
||||
|
||||
template <typename T>
|
||||
typename 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
|
||||
|
||||
// Implementation
|
||||
|
||||
namespace hash_detail
|
||||
{
|
||||
template <class T>
|
||||
inline std::size_t hash_value_signed(T val)
|
||||
{
|
||||
const unsigned int size_t_bits = std::numeric_limits<std::size_t>::digits;
|
||||
// ceiling(std::numeric_limits<T>::digits / size_t_bits) - 1
|
||||
const int length = (std::numeric_limits<T>::digits - 1)
|
||||
/ static_cast<int>(size_t_bits);
|
||||
|
||||
std::size_t seed = 0;
|
||||
T positive = val < 0 ? -1 - val : val;
|
||||
|
||||
// Hopefully, this loop can be unrolled.
|
||||
for(unsigned int i = length * size_t_bits; i > 0; i -= size_t_bits)
|
||||
{
|
||||
seed ^= (std::size_t) (positive >> i) + (seed<<6) + (seed>>2);
|
||||
}
|
||||
seed ^= (std::size_t) val + (seed<<6) + (seed>>2);
|
||||
|
||||
return seed;
|
||||
}
|
||||
|
||||
template <class T>
|
||||
inline std::size_t hash_value_unsigned(T val)
|
||||
{
|
||||
const unsigned int size_t_bits = std::numeric_limits<std::size_t>::digits;
|
||||
// ceiling(std::numeric_limits<T>::digits / size_t_bits) - 1
|
||||
const int length = (std::numeric_limits<T>::digits - 1)
|
||||
/ static_cast<int>(size_t_bits);
|
||||
|
||||
std::size_t seed = 0;
|
||||
|
||||
// Hopefully, this loop can be unrolled.
|
||||
for(unsigned int i = length * size_t_bits; i > 0; i -= size_t_bits)
|
||||
{
|
||||
seed ^= (std::size_t) (val >> i) + (seed<<6) + (seed>>2);
|
||||
}
|
||||
seed ^= (std::size_t) val + (seed<<6) + (seed>>2);
|
||||
|
||||
return seed;
|
||||
}
|
||||
|
||||
template <typename SizeT>
|
||||
inline void hash_combine_impl(SizeT& seed, SizeT value)
|
||||
{
|
||||
seed ^= value + 0x9e3779b9 + (seed<<6) + (seed>>2);
|
||||
}
|
||||
|
||||
inline void hash_combine_impl(boost::uint32_t& h1,
|
||||
boost::uint32_t k1)
|
||||
{
|
||||
const uint32_t c1 = 0xcc9e2d51;
|
||||
const uint32_t c2 = 0x1b873593;
|
||||
|
||||
k1 *= c1;
|
||||
k1 = BOOST_FUNCTIONAL_HASH_ROTL32(k1,15);
|
||||
k1 *= c2;
|
||||
|
||||
h1 ^= k1;
|
||||
h1 = BOOST_FUNCTIONAL_HASH_ROTL32(h1,13);
|
||||
h1 = h1*5+0xe6546b64;
|
||||
}
|
||||
|
||||
|
||||
// Don't define 64-bit hash combine on platforms without 64 bit integers,
|
||||
// and also not for 32-bit gcc as it warns about the 64-bit constant.
|
||||
#if !defined(BOOST_NO_INT64_T) && \
|
||||
!(defined(__GNUC__) && ULONG_MAX == 0xffffffff)
|
||||
|
||||
inline void hash_combine_impl(boost::uint64_t& h,
|
||||
boost::uint64_t k)
|
||||
{
|
||||
const boost::uint64_t m = UINT64_C(0xc6a4a7935bd1e995);
|
||||
const int r = 47;
|
||||
|
||||
k *= m;
|
||||
k ^= k >> r;
|
||||
k *= m;
|
||||
|
||||
h ^= k;
|
||||
h *= m;
|
||||
|
||||
// Completely arbitrary number, to prevent 0's
|
||||
// from hashing to 0.
|
||||
h += 0xe6546b64;
|
||||
}
|
||||
|
||||
#endif // BOOST_NO_INT64_T
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
typename boost::hash_detail::basic_numbers<T>::type hash_value(T v)
|
||||
{
|
||||
return static_cast<std::size_t>(v);
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
typename boost::hash_detail::long_numbers<T>::type hash_value(T v)
|
||||
{
|
||||
return hash_detail::hash_value_signed(v);
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
typename boost::hash_detail::ulong_numbers<T>::type hash_value(T v)
|
||||
{
|
||||
return hash_detail::hash_value_unsigned(v);
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
typename boost::enable_if<boost::is_enum<T>, std::size_t>::type
|
||||
hash_value(T v)
|
||||
{
|
||||
return static_cast<std::size_t>(v);
|
||||
}
|
||||
|
||||
// Implementation by Alberto Barbati and Dave Harris.
|
||||
#if !BOOST_WORKAROUND(__DMC__, <= 0x848)
|
||||
template <class T> std::size_t hash_value(T* const& v)
|
||||
#else
|
||||
template <class T> std::size_t hash_value(T* v)
|
||||
#endif
|
||||
{
|
||||
#if defined(__VMS) && __INITIAL_POINTER_SIZE == 64
|
||||
// for some reason ptrdiff_t on OpenVMS compiler with
|
||||
// 64 bit is not 64 bit !!!
|
||||
std::size_t x = static_cast<std::size_t>(
|
||||
reinterpret_cast<long long int>(v));
|
||||
#else
|
||||
std::size_t x = static_cast<std::size_t>(
|
||||
reinterpret_cast<std::ptrdiff_t>(v));
|
||||
#endif
|
||||
return x + (x >> 3);
|
||||
}
|
||||
|
||||
#if defined(BOOST_MSVC)
|
||||
#pragma warning(push)
|
||||
#if BOOST_MSVC <= 1400
|
||||
#pragma warning(disable:4267) // 'argument' : conversion from 'size_t' to
|
||||
// 'unsigned int', possible loss of data
|
||||
// A misguided attempt to detect 64-bit
|
||||
// incompatability.
|
||||
#endif
|
||||
#endif
|
||||
|
||||
template <class T>
|
||||
inline void hash_combine(std::size_t& seed, T const& v)
|
||||
{
|
||||
boost::hash<T> hasher;
|
||||
return boost::hash_detail::hash_combine_impl(seed, hasher(v));
|
||||
}
|
||||
|
||||
#if defined(BOOST_MSVC)
|
||||
#pragma warning(pop)
|
||||
#endif
|
||||
|
||||
template <class It>
|
||||
inline std::size_t hash_range(It first, It last)
|
||||
{
|
||||
std::size_t seed = 0;
|
||||
|
||||
for(; first != last; ++first)
|
||||
{
|
||||
hash_combine(seed, *first);
|
||||
}
|
||||
|
||||
return seed;
|
||||
}
|
||||
|
||||
template <class It>
|
||||
inline void hash_range(std::size_t& seed, It first, It last)
|
||||
{
|
||||
for(; first != last; ++first)
|
||||
{
|
||||
hash_combine(seed, *first);
|
||||
}
|
||||
}
|
||||
|
||||
#if BOOST_WORKAROUND(__BORLANDC__, BOOST_TESTED_AT(0x551))
|
||||
template <class T>
|
||||
inline std::size_t hash_range(T* first, T* last)
|
||||
{
|
||||
std::size_t seed = 0;
|
||||
|
||||
for(; first != last; ++first)
|
||||
{
|
||||
boost::hash<T> hasher;
|
||||
seed ^= hasher(*first) + 0x9e3779b9 + (seed<<6) + (seed>>2);
|
||||
}
|
||||
|
||||
return seed;
|
||||
}
|
||||
|
||||
template <class T>
|
||||
inline void hash_range(std::size_t& seed, T* first, T* last)
|
||||
{
|
||||
for(; first != last; ++first)
|
||||
{
|
||||
boost::hash<T> hasher;
|
||||
seed ^= hasher(*first) + 0x9e3779b9 + (seed<<6) + (seed>>2);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
#if !defined(BOOST_NO_FUNCTION_TEMPLATE_ORDERING)
|
||||
template< class T, unsigned N >
|
||||
inline std::size_t hash_value(const T (&x)[N])
|
||||
{
|
||||
return hash_range(x, x + N);
|
||||
}
|
||||
|
||||
template< class T, unsigned N >
|
||||
inline std::size_t hash_value(T (&x)[N])
|
||||
{
|
||||
return hash_range(x, x + N);
|
||||
}
|
||||
#endif
|
||||
|
||||
template <class Ch, class A>
|
||||
inline std::size_t hash_value(
|
||||
std::basic_string<Ch, std::BOOST_HASH_CHAR_TRAITS<Ch>, A> const& v)
|
||||
{
|
||||
return hash_range(v.begin(), v.end());
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
typename boost::hash_detail::float_numbers<T>::type hash_value(T v)
|
||||
{
|
||||
return boost::hash_detail::float_hash_value(v);
|
||||
}
|
||||
|
||||
#if !defined(BOOST_NO_CXX11_HDR_TYPEINDEX)
|
||||
inline std::size_t hash_value(std::type_index v)
|
||||
{
|
||||
return v.hash_code();
|
||||
}
|
||||
#endif
|
||||
|
||||
//
|
||||
// boost::hash
|
||||
//
|
||||
|
||||
// Define the specializations required by the standard. The general purpose
|
||||
// boost::hash is defined later in extensions.hpp if
|
||||
// BOOST_HASH_NO_EXTENSIONS is not defined.
|
||||
|
||||
// BOOST_HASH_SPECIALIZE - define a specialization for a type which is
|
||||
// passed by copy.
|
||||
//
|
||||
// BOOST_HASH_SPECIALIZE_REF - define a specialization for a type which is
|
||||
// passed by const reference.
|
||||
//
|
||||
// These are undefined later.
|
||||
|
||||
#define BOOST_HASH_SPECIALIZE(type) \
|
||||
template <> struct hash<type> \
|
||||
: public boost::hash_detail::hash_base<type> \
|
||||
{ \
|
||||
std::size_t operator()(type v) const \
|
||||
{ \
|
||||
return boost::hash_value(v); \
|
||||
} \
|
||||
};
|
||||
|
||||
#define BOOST_HASH_SPECIALIZE_REF(type) \
|
||||
template <> struct hash<type> \
|
||||
: public boost::hash_detail::hash_base<type> \
|
||||
{ \
|
||||
std::size_t operator()(type const& v) const \
|
||||
{ \
|
||||
return boost::hash_value(v); \
|
||||
} \
|
||||
};
|
||||
|
||||
BOOST_HASH_SPECIALIZE(bool)
|
||||
BOOST_HASH_SPECIALIZE(char)
|
||||
BOOST_HASH_SPECIALIZE(signed char)
|
||||
BOOST_HASH_SPECIALIZE(unsigned char)
|
||||
#if !defined(BOOST_NO_INTRINSIC_WCHAR_T)
|
||||
BOOST_HASH_SPECIALIZE(wchar_t)
|
||||
#endif
|
||||
#if !defined(BOOST_NO_CXX11_CHAR16_T)
|
||||
BOOST_HASH_SPECIALIZE(char16_t)
|
||||
#endif
|
||||
#if !defined(BOOST_NO_CXX11_CHAR32_T)
|
||||
BOOST_HASH_SPECIALIZE(char32_t)
|
||||
#endif
|
||||
BOOST_HASH_SPECIALIZE(short)
|
||||
BOOST_HASH_SPECIALIZE(unsigned short)
|
||||
BOOST_HASH_SPECIALIZE(int)
|
||||
BOOST_HASH_SPECIALIZE(unsigned int)
|
||||
BOOST_HASH_SPECIALIZE(long)
|
||||
BOOST_HASH_SPECIALIZE(unsigned long)
|
||||
|
||||
BOOST_HASH_SPECIALIZE(float)
|
||||
BOOST_HASH_SPECIALIZE(double)
|
||||
BOOST_HASH_SPECIALIZE(long double)
|
||||
|
||||
BOOST_HASH_SPECIALIZE_REF(std::string)
|
||||
#if !defined(BOOST_NO_STD_WSTRING) && !defined(BOOST_NO_INTRINSIC_WCHAR_T)
|
||||
BOOST_HASH_SPECIALIZE_REF(std::wstring)
|
||||
#endif
|
||||
#if !defined(BOOST_NO_CXX11_CHAR16_T)
|
||||
BOOST_HASH_SPECIALIZE_REF(std::basic_string<char16_t>)
|
||||
#endif
|
||||
#if !defined(BOOST_NO_CXX11_CHAR32_T)
|
||||
BOOST_HASH_SPECIALIZE_REF(std::basic_string<char32_t>)
|
||||
#endif
|
||||
|
||||
#if !defined(BOOST_NO_LONG_LONG)
|
||||
BOOST_HASH_SPECIALIZE(boost::long_long_type)
|
||||
BOOST_HASH_SPECIALIZE(boost::ulong_long_type)
|
||||
#endif
|
||||
|
||||
#if defined(BOOST_HAS_INT128)
|
||||
BOOST_HASH_SPECIALIZE(boost::int128_type)
|
||||
BOOST_HASH_SPECIALIZE(boost::uint128_type)
|
||||
#endif
|
||||
|
||||
#if !defined(BOOST_NO_CXX11_HDR_TYPEINDEX)
|
||||
BOOST_HASH_SPECIALIZE(std::type_index)
|
||||
#endif
|
||||
|
||||
#undef BOOST_HASH_SPECIALIZE
|
||||
#undef BOOST_HASH_SPECIALIZE_REF
|
||||
|
||||
// Specializing boost::hash for pointers.
|
||||
|
||||
#if !defined(BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION)
|
||||
|
||||
template <class T>
|
||||
struct hash<T*>
|
||||
: public boost::hash_detail::hash_base<T*>
|
||||
{
|
||||
std::size_t operator()(T* v) const
|
||||
{
|
||||
#if !BOOST_WORKAROUND(__SUNPRO_CC, <= 0x590)
|
||||
return boost::hash_value(v);
|
||||
#else
|
||||
std::size_t x = static_cast<std::size_t>(
|
||||
reinterpret_cast<std::ptrdiff_t>(v));
|
||||
|
||||
return x + (x >> 3);
|
||||
#endif
|
||||
}
|
||||
};
|
||||
|
||||
#else
|
||||
|
||||
// For compilers without partial specialization, we define a
|
||||
// boost::hash for all remaining types. But hash_impl is only defined
|
||||
// for pointers in 'extensions.hpp' - so when BOOST_HASH_NO_EXTENSIONS
|
||||
// is defined there will still be a compile error for types not supported
|
||||
// in the standard.
|
||||
|
||||
namespace hash_detail
|
||||
{
|
||||
template <bool IsPointer>
|
||||
struct hash_impl;
|
||||
|
||||
template <>
|
||||
struct hash_impl<true>
|
||||
{
|
||||
template <class T>
|
||||
struct inner
|
||||
: public boost::hash_detail::hash_base<T>
|
||||
{
|
||||
std::size_t operator()(T val) const
|
||||
{
|
||||
#if !BOOST_WORKAROUND(__SUNPRO_CC, <= 590)
|
||||
return boost::hash_value(val);
|
||||
#else
|
||||
std::size_t x = static_cast<std::size_t>(
|
||||
reinterpret_cast<std::ptrdiff_t>(val));
|
||||
|
||||
return x + (x >> 3);
|
||||
#endif
|
||||
}
|
||||
};
|
||||
};
|
||||
}
|
||||
|
||||
template <class T> struct hash
|
||||
: public boost::hash_detail::hash_impl<boost::is_pointer<T>::value>
|
||||
::BOOST_NESTED_TEMPLATE inner<T>
|
||||
{
|
||||
};
|
||||
|
||||
#endif
|
||||
}
|
||||
|
||||
#undef BOOST_HASH_CHAR_TRAITS
|
||||
#undef BOOST_FUNCTIONAL_HASH_ROTL32
|
||||
|
||||
#if defined(BOOST_MSVC)
|
||||
#pragma warning(pop)
|
||||
#endif
|
||||
|
||||
#endif // BOOST_FUNCTIONAL_HASH_HASH_HPP
|
||||
|
||||
// Include this outside of the include guards in case the file is included
|
||||
// twice - once with BOOST_HASH_NO_EXTENSIONS defined, and then with it
|
||||
// undefined.
|
||||
|
||||
#if !defined(BOOST_HASH_NO_EXTENSIONS) \
|
||||
&& !defined(BOOST_FUNCTIONAL_HASH_EXTENSIONS_HPP)
|
||||
#include <boost/container_hash/hash/extensions.hpp>
|
||||
#endif
|
@@ -1,36 +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)
|
||||
|
||||
// Based on Peter Dimov's proposal
|
||||
// http://www.open-std.org/JTC1/SC22/WG21/docs/papers/2005/n1756.pdf
|
||||
// issue 6.18.
|
||||
|
||||
#if !defined(BOOST_FUNCTIONAL_HASH_FWD_HPP)
|
||||
#define BOOST_FUNCTIONAL_HASH_FWD_HPP
|
||||
|
||||
#include <boost/config/workaround.hpp>
|
||||
#include <cstddef>
|
||||
|
||||
#if defined(BOOST_HAS_PRAGMA_ONCE)
|
||||
#pragma once
|
||||
#endif
|
||||
|
||||
|
||||
namespace boost
|
||||
{
|
||||
template <class T> struct hash;
|
||||
|
||||
template <class T> void hash_combine(std::size_t& seed, T const& v);
|
||||
|
||||
template <class It> std::size_t hash_range(It, It);
|
||||
template <class It> void hash_range(std::size_t&, It, It);
|
||||
|
||||
#if BOOST_WORKAROUND(__BORLANDC__, BOOST_TESTED_AT(0x551))
|
||||
template <class T> inline std::size_t hash_range(T*, T*);
|
||||
template <class T> inline void hash_range(std::size_t&, T*, T*);
|
||||
#endif
|
||||
}
|
||||
|
||||
#endif
|
@@ -3,9 +3,34 @@
|
||||
// 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)
|
||||
|
||||
#include <boost/config.hpp>
|
||||
// Based on Peter Dimov's proposal
|
||||
// http://www.open-std.org/JTC1/SC22/WG21/docs/papers/2005/n1756.pdf
|
||||
// issue 6.18.
|
||||
|
||||
#if !defined(BOOST_FUNCTIONAL_HASH_FWD_HPP)
|
||||
#define BOOST_FUNCTIONAL_HASH_FWD_HPP
|
||||
|
||||
#include <boost/config/workaround.hpp>
|
||||
#include <cstddef>
|
||||
|
||||
#if defined(BOOST_HAS_PRAGMA_ONCE)
|
||||
#pragma once
|
||||
#endif
|
||||
|
||||
#include <boost/container_hash/hash/hash_fwd.hpp>
|
||||
|
||||
namespace boost
|
||||
{
|
||||
template <class T> struct hash;
|
||||
|
||||
template <class T> void hash_combine(std::size_t& seed, T const& v);
|
||||
|
||||
template <class It> std::size_t hash_range(It, It);
|
||||
template <class It> void hash_range(std::size_t&, It, It);
|
||||
|
||||
#if BOOST_WORKAROUND(__BORLANDC__, BOOST_TESTED_AT(0x551))
|
||||
template <class T> inline std::size_t hash_range(T*, T*);
|
||||
template <class T> inline void hash_range(std::size_t&, T*, T*);
|
||||
#endif
|
||||
}
|
||||
|
||||
#endif
|
||||
|
@@ -3,4 +3,4 @@
|
||||
// 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)
|
||||
|
||||
#include <boost/container_hash/hash/hash.hpp>
|
||||
#include <boost/container_hash/hash.hpp>
|
||||
|
@@ -3,4 +3,4 @@
|
||||
// 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)
|
||||
|
||||
#include <boost/container_hash/hash/extensions.hpp>
|
||||
#include <boost/container_hash/extensions.hpp>
|
||||
|
@@ -3,4 +3,4 @@
|
||||
// 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)
|
||||
|
||||
#include <boost/container_hash/hash/hash.hpp>
|
||||
#include <boost/container_hash/hash.hpp>
|
||||
|
@@ -3,4 +3,4 @@
|
||||
// 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)
|
||||
|
||||
#include <boost/container_hash/hash/hash_fwd.hpp>
|
||||
#include <boost/container_hash/hash_fwd.hpp>
|
||||
|
@@ -3,4 +3,4 @@
|
||||
// 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)
|
||||
|
||||
#include <boost/container_hash/hash/hash_fwd.hpp>
|
||||
#include <boost/container_hash/hash_fwd.hpp>
|
||||
|
@@ -20,6 +20,7 @@ project hash-tests
|
||||
|
||||
test-suite container_hash/hash
|
||||
:
|
||||
[ run hash_info.cpp : : : <test-info>always_show_run_output ]
|
||||
[ compile check_float_funcs.cpp ]
|
||||
[ run hash_fwd_test_1.cpp ]
|
||||
[ run hash_fwd_test_2.cpp ]
|
||||
@@ -42,7 +43,10 @@ test-suite container_hash/hash
|
||||
[ run hash_set_test.cpp ]
|
||||
[ run hash_map_test.cpp ]
|
||||
[ run hash_complex_test.cpp ]
|
||||
[ run hash_optional_test.cpp ]
|
||||
[ run hash_variant_test.cpp ]
|
||||
[ run hash_type_index_test.cpp ]
|
||||
[ run hash_system_error_test.cpp ]
|
||||
[ run hash_std_array_test.cpp ]
|
||||
[ run hash_std_tuple_test.cpp ]
|
||||
[ run hash_std_smart_ptr_test.cpp ]
|
||||
|
@@ -5,14 +5,16 @@
|
||||
|
||||
#include <boost/config.hpp>
|
||||
#include <boost/static_assert.hpp>
|
||||
#include <boost/type_traits/is_base_and_derived.hpp>
|
||||
#include <boost/type_traits/is_same.hpp>
|
||||
|
||||
template <class T>
|
||||
void compile_time_tests(T*)
|
||||
{
|
||||
#if !defined(_HAS_AUTO_PTR_ETC) || _HAS_AUTO_PTR_ETC
|
||||
BOOST_STATIC_ASSERT((boost::is_base_and_derived<
|
||||
std::unary_function<T, std::size_t>, BOOST_HASH_TEST_NAMESPACE::hash<T> >::value));
|
||||
#endif
|
||||
BOOST_STATIC_ASSERT((boost::is_same<T,
|
||||
typename BOOST_HASH_TEST_NAMESPACE::hash<T>::argument_type
|
||||
>::value));
|
||||
BOOST_STATIC_ASSERT((boost::is_same<std::size_t,
|
||||
typename BOOST_HASH_TEST_NAMESPACE::hash<T>::result_type
|
||||
>::value));
|
||||
}
|
||||
|
||||
|
@@ -3,14 +3,14 @@
|
||||
// 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)
|
||||
|
||||
// Check that boost/container_hash/hash/extensions.hpp works okay.
|
||||
// Check that boost/container_hash/extensions.hpp works okay.
|
||||
//
|
||||
// It probably should be in boost/container_hash/hash/detail, but since it isn't it
|
||||
// It probably should be in boost/container_hash/detail, but since it isn't it
|
||||
// should work.
|
||||
|
||||
#include "./config.hpp"
|
||||
|
||||
#include <boost/container_hash/hash/extensions.hpp>
|
||||
#include <boost/container_hash/extensions.hpp>
|
||||
|
||||
int main() {
|
||||
int x[2] = { 2, 3 };
|
||||
|
@@ -14,8 +14,8 @@
|
||||
#include <boost/core/lightweight_test.hpp>
|
||||
|
||||
#include <cmath>
|
||||
#include <boost/container_hash/hash/detail/limits.hpp>
|
||||
#include <boost/container_hash/hash/detail/float_functions.hpp>
|
||||
#include <boost/container_hash/detail/limits.hpp>
|
||||
#include <boost/container_hash/detail/float_functions.hpp>
|
||||
#include <boost/config/workaround.hpp>
|
||||
|
||||
#include <iostream>
|
||||
|
101
test/hash_info.cpp
Normal file
101
test/hash_info.cpp
Normal file
@@ -0,0 +1,101 @@
|
||||
|
||||
// Copyright 2017 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)
|
||||
|
||||
// Not a test, just a small program to write out configuration info
|
||||
|
||||
#include <boost/container_hash/hash.hpp>
|
||||
#include <iostream>
|
||||
#include <algorithm>
|
||||
|
||||
#if defined(BOOST_MSVC)
|
||||
|
||||
struct msvc_version {
|
||||
unsigned version;
|
||||
char const* description;
|
||||
|
||||
friend bool operator<(msvc_version const& v1, msvc_version const& v2) {
|
||||
return v1.version < v2.version;
|
||||
}
|
||||
};
|
||||
|
||||
void write_compiler_info() {
|
||||
// From:
|
||||
// https://en.wikipedia.org/wiki/Microsoft_Visual_C%2B%2B
|
||||
// https://blogs.msdn.microsoft.com/vcblog/2017/11/15/side-by-side-minor-version-msvc-toolsets-in-visual-studio-2017/
|
||||
msvc_version versions[] = {
|
||||
{0, "Old Visual C++"},
|
||||
{1000, "Visual C++ 4.x, VS4.0?"},
|
||||
{1100, "Visual C++ 5.0, VS97"},
|
||||
{1200, "Visual C++ 6.0, VS6.0"},
|
||||
{1300, "Visual C++ 7.0, VS.NET 2002"},
|
||||
{1310, "Visual C++ 7.1, VS.NET 2003"},
|
||||
{1400, "Visual C++ 8.0, VS2005"},
|
||||
{1500, "Visual C++ 9.0, VS2008"},
|
||||
{1600, "Visual C++ 10.0, VS2010"},
|
||||
{1700, "Visual C++ 11.0, VS2012"},
|
||||
{1800, "Visual C++ 12.0, VS2013"},
|
||||
{1900, "Visual C++ 14.00, VS2015"},
|
||||
{1910, "Visual C++ 14.10, VS2017 15.1/2"},
|
||||
{1911, "Visual C++ 14.11, VS2017 15.3/4"},
|
||||
{1912, "Visual C++ 14.12, VS2017 15.5"}
|
||||
};
|
||||
|
||||
msvc_version msvc = { BOOST_MSVC, "" };
|
||||
msvc_version* v = std::upper_bound(versions,
|
||||
versions + sizeof(versions) / sizeof(*versions),
|
||||
msvc) - 1;
|
||||
unsigned difference = msvc.version - v->version;
|
||||
|
||||
std::cout << v->description << std::endl;
|
||||
if (difference) {
|
||||
std::cout << "+" << difference << std::endl;
|
||||
}
|
||||
}
|
||||
|
||||
#else
|
||||
|
||||
void write_compiler_info() {
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
int main() {
|
||||
write_compiler_info();
|
||||
|
||||
#if defined(__cplusplus)
|
||||
std::cout << "__cplusplus: "
|
||||
<< __cplusplus
|
||||
<< std::endl;
|
||||
#endif
|
||||
|
||||
std::cout << "BOOST_HASH_CXX17: "
|
||||
<< BOOST_HASH_CXX17
|
||||
<< std::endl;
|
||||
|
||||
std::cout << "BOOST_HASH_HAS_STRING_VIEW: "
|
||||
<< BOOST_HASH_HAS_STRING_VIEW
|
||||
<< std::endl;
|
||||
|
||||
std::cout << "BOOST_HASH_HAS_OPTIONAL: "
|
||||
<< BOOST_HASH_HAS_OPTIONAL
|
||||
<< std::endl;
|
||||
|
||||
std::cout << "BOOST_HASH_HAS_VARIANT: "
|
||||
<< BOOST_HASH_HAS_VARIANT
|
||||
<< std::endl;
|
||||
|
||||
#if defined(BOOST_NO_CXX11_HDR_TYPEINDEX)
|
||||
std::cout << "No <typeindex>" << std::endl;
|
||||
#else
|
||||
std::cout << "<typeindex>" << std::endl;
|
||||
#endif
|
||||
|
||||
#if defined(BOOST_NO_CXX11_HDR_SYSTEM_ERROR)
|
||||
std::cout << "No <system_error>" << std::endl;
|
||||
#else
|
||||
std::cout << "<system_error>" << std::endl;
|
||||
#endif
|
||||
|
||||
}
|
@@ -14,7 +14,7 @@
|
||||
#include <iostream>
|
||||
#include <boost/core/lightweight_test.hpp>
|
||||
|
||||
#include <boost/container_hash/hash/detail/limits.hpp>
|
||||
#include <boost/container_hash/detail/limits.hpp>
|
||||
#include <boost/core/enable_if.hpp>
|
||||
|
||||
#include "./compile_time.hpp"
|
||||
|
70
test/hash_optional_test.cpp
Normal file
70
test/hash_optional_test.cpp
Normal file
@@ -0,0 +1,70 @@
|
||||
|
||||
// Copyright 2018 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)
|
||||
|
||||
#include "./config.hpp"
|
||||
|
||||
#ifndef BOOST_HASH_TEST_STD_INCLUDES
|
||||
# include <boost/container_hash/hash.hpp>
|
||||
#endif
|
||||
#include <boost/config.hpp>
|
||||
#include <boost/core/lightweight_test.hpp>
|
||||
|
||||
#if BOOST_HASH_HAS_OPTIONAL
|
||||
|
||||
#include <optional>
|
||||
#include <string>
|
||||
|
||||
void test_optional_int()
|
||||
{
|
||||
std::optional<int> x1a;
|
||||
std::optional<int> x1b;
|
||||
std::optional<int> x2a(10);
|
||||
std::optional<int> x2b(x2a);
|
||||
std::optional<int> x3(20);
|
||||
|
||||
boost::hash<std::optional<int> > hasher;
|
||||
|
||||
BOOST_TEST(hasher(x1a) == hasher(x1a));
|
||||
BOOST_TEST(hasher(x1a) == hasher(x1b));
|
||||
BOOST_TEST(hasher(x1a) != hasher(x2a));
|
||||
BOOST_TEST(hasher(x1a) != hasher(x3));
|
||||
BOOST_TEST(hasher(x2a) == hasher(x2a));
|
||||
BOOST_TEST(hasher(x2b) == hasher(x2b));
|
||||
BOOST_TEST(hasher(x2a) != hasher(x3));
|
||||
BOOST_TEST(hasher(x3) == hasher(x3));
|
||||
}
|
||||
|
||||
void test_optional_string()
|
||||
{
|
||||
std::optional<std::string> x1a;
|
||||
std::optional<std::string> x1b;
|
||||
std::optional<std::string> x2a("10");
|
||||
std::optional<std::string> x2b(x2a);
|
||||
std::optional<std::string> x3("20");
|
||||
|
||||
boost::hash<std::optional<std::string> > hasher;
|
||||
|
||||
BOOST_TEST(hasher(x1a) == hasher(x1a));
|
||||
BOOST_TEST(hasher(x1a) == hasher(x1b));
|
||||
BOOST_TEST(hasher(x1a) != hasher(x2a));
|
||||
BOOST_TEST(hasher(x1a) != hasher(x3));
|
||||
BOOST_TEST(hasher(x2a) == hasher(x2a));
|
||||
BOOST_TEST(hasher(x2b) == hasher(x2b));
|
||||
BOOST_TEST(hasher(x2a) != hasher(x3));
|
||||
BOOST_TEST(hasher(x3) == hasher(x3));
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
int main()
|
||||
{
|
||||
#if BOOST_HASH_HAS_OPTIONAL
|
||||
test_optional_int();
|
||||
test_optional_string();
|
||||
#else
|
||||
BOOST_LIGHTWEIGHT_TEST_OSTREAM << "<optional> not available." << std::endl;
|
||||
#endif
|
||||
return boost::report_errors();
|
||||
}
|
@@ -130,6 +130,37 @@ void u32string_tests()
|
||||
}
|
||||
#endif
|
||||
|
||||
template <typename StringType>
|
||||
void generic_string_tests(StringType*)
|
||||
{
|
||||
std::string x1(1, '\0');
|
||||
std::string x2(2, '\0');
|
||||
std::string x3(3, '\0');
|
||||
std::string x4(10, '\0');
|
||||
std::string x5 = x2 + "hello" + x2;
|
||||
|
||||
StringType strings[] = {
|
||||
"",
|
||||
"hello",
|
||||
x1,
|
||||
x2,
|
||||
x3,
|
||||
x4,
|
||||
x5
|
||||
};
|
||||
|
||||
std::size_t const strings_length = sizeof(strings) / sizeof(StringType);
|
||||
boost::hash<StringType> hash;
|
||||
|
||||
for (std::size_t i = 0; i < strings_length; ++i) {
|
||||
std::size_t hash_i = hash(strings[i]);
|
||||
for (std::size_t j = 0; j < strings_length; ++j) {
|
||||
std::size_t hash_j = hash(strings[j]);
|
||||
BOOST_TEST((hash_i == hash_j) == (i == j));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
int main()
|
||||
{
|
||||
string_tests();
|
||||
@@ -143,5 +174,11 @@ int main()
|
||||
#if !defined(BOOST_NO_CXX11_CHAR32_T)
|
||||
u32string_tests();
|
||||
#endif
|
||||
|
||||
generic_string_tests((std::string*) 0);
|
||||
#if BOOST_HASH_HAS_STRING_VIEW
|
||||
generic_string_tests((std::string_view*) 0);
|
||||
#endif
|
||||
|
||||
return boost::report_errors();
|
||||
}
|
||||
|
55
test/hash_system_error_test.cpp
Normal file
55
test/hash_system_error_test.cpp
Normal file
@@ -0,0 +1,55 @@
|
||||
|
||||
// Copyright 2018 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)
|
||||
|
||||
#include "./config.hpp"
|
||||
|
||||
#ifndef BOOST_HASH_TEST_STD_INCLUDES
|
||||
# include <boost/container_hash/hash.hpp>
|
||||
#endif
|
||||
#include <boost/config.hpp>
|
||||
#include <boost/core/lightweight_test.hpp>
|
||||
|
||||
#if !defined(BOOST_NO_CXX11_HDR_SYSTEM_ERROR)
|
||||
|
||||
#include <system_error>
|
||||
|
||||
void test_error_code()
|
||||
{
|
||||
std::error_code err1a = std::make_error_code(std::errc::argument_list_too_long);
|
||||
std::error_code err1b = std::make_error_code(std::errc::argument_list_too_long);
|
||||
std::error_code err2 = std::make_error_code(std::errc::bad_file_descriptor);
|
||||
|
||||
boost::hash<std::error_code> hasher;
|
||||
|
||||
BOOST_TEST(hasher(err1a) == hasher(err1a));
|
||||
BOOST_TEST(hasher(err1a) == hasher(err1b));
|
||||
BOOST_TEST(hasher(err1a) != hasher(err2));
|
||||
}
|
||||
|
||||
void test_error_condition()
|
||||
{
|
||||
std::error_condition err1a = std::make_error_condition(std::errc::directory_not_empty);
|
||||
std::error_condition err1b = std::make_error_condition(std::errc::directory_not_empty);
|
||||
std::error_condition err2 = std::make_error_condition(std::errc::filename_too_long);
|
||||
|
||||
boost::hash<std::error_condition> hasher;
|
||||
|
||||
BOOST_TEST(hasher(err1a) == hasher(err1a));
|
||||
BOOST_TEST(hasher(err1a) == hasher(err1b));
|
||||
BOOST_TEST(hasher(err1a) != hasher(err2));
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
int main()
|
||||
{
|
||||
#if !defined(BOOST_NO_CXX11_HDR_SYSTEM_ERROR)
|
||||
test_error_code();
|
||||
test_error_condition();
|
||||
#else
|
||||
BOOST_LIGHTWEIGHT_TEST_OSTREAM << "<system_error> not available." << std::endl;
|
||||
#endif
|
||||
return boost::report_errors();
|
||||
}
|
100
test/hash_variant_test.cpp
Normal file
100
test/hash_variant_test.cpp
Normal file
@@ -0,0 +1,100 @@
|
||||
|
||||
// Copyright 2018 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)
|
||||
|
||||
#include "./config.hpp"
|
||||
|
||||
#ifndef BOOST_HASH_TEST_STD_INCLUDES
|
||||
# include <boost/container_hash/hash.hpp>
|
||||
#endif
|
||||
#include <boost/config.hpp>
|
||||
#include <boost/core/lightweight_test.hpp>
|
||||
|
||||
#if BOOST_HASH_HAS_VARIANT
|
||||
|
||||
#include <variant>
|
||||
#include <string>
|
||||
|
||||
void test_monostate()
|
||||
{
|
||||
std::monostate x1;
|
||||
std::monostate x2;
|
||||
|
||||
boost::hash<std::monostate> hasher;
|
||||
|
||||
BOOST_TEST(hasher(x1) == hasher(x2));
|
||||
}
|
||||
|
||||
void test_variant_int()
|
||||
{
|
||||
std::variant<std::monostate, int> x1a;
|
||||
std::variant<std::monostate, int> x1b;
|
||||
std::variant<std::monostate, int> x2a(10);
|
||||
std::variant<std::monostate, int> x2b(x2a);
|
||||
std::variant<std::monostate, int> x3(20);
|
||||
|
||||
boost::hash<std::variant<std::monostate, int> > hasher;
|
||||
|
||||
BOOST_TEST(hasher(x1a) == hasher(x1a));
|
||||
BOOST_TEST(hasher(x1a) == hasher(x1b));
|
||||
BOOST_TEST(hasher(x1a) != hasher(x2a));
|
||||
BOOST_TEST(hasher(x1a) != hasher(x3));
|
||||
BOOST_TEST(hasher(x2a) == hasher(x2a));
|
||||
BOOST_TEST(hasher(x2b) == hasher(x2b));
|
||||
BOOST_TEST(hasher(x2a) != hasher(x3));
|
||||
BOOST_TEST(hasher(x3) == hasher(x3));
|
||||
}
|
||||
|
||||
struct custom1 {
|
||||
int value;
|
||||
friend std::size_t hash_value(custom1 v) { return boost::hash_value(v.value); }
|
||||
};
|
||||
|
||||
struct custom2 {
|
||||
int value;
|
||||
friend std::size_t hash_value(custom2 v) { return boost::hash_value(v.value); }
|
||||
};
|
||||
|
||||
void test_variant_unique_types()
|
||||
{
|
||||
custom1 x11 = { 0 };
|
||||
custom1 x12 = { 1 };
|
||||
custom2 x21 = { 0 };
|
||||
custom2 x22 = { 1 };
|
||||
|
||||
boost::hash<custom1> hasher1;
|
||||
boost::hash<custom2> hasher2;
|
||||
|
||||
BOOST_TEST(hasher1(x11) == hasher2(x21));
|
||||
BOOST_TEST(hasher1(x11) != hasher2(x22));
|
||||
BOOST_TEST(hasher1(x12) != hasher2(x21));
|
||||
BOOST_TEST(hasher1(x12) == hasher2(x22));
|
||||
|
||||
typedef std::variant<custom1, custom2> variant_type;
|
||||
|
||||
variant_type y11(x11);
|
||||
variant_type y12(x12);
|
||||
variant_type y21(x21);
|
||||
variant_type y22(x22);
|
||||
|
||||
boost::hash<variant_type> hasher;
|
||||
|
||||
BOOST_TEST(hasher(y11) != hasher(y21));
|
||||
BOOST_TEST(hasher(y11) != hasher(y22));
|
||||
BOOST_TEST(hasher(y12) != hasher(y21));
|
||||
BOOST_TEST(hasher(y12) != hasher(y22));
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
int main()
|
||||
{
|
||||
#if BOOST_HASH_HAS_VARIANT
|
||||
test_variant_int();
|
||||
test_variant_unique_types();
|
||||
#else
|
||||
BOOST_LIGHTWEIGHT_TEST_OSTREAM << "<variant> not available." << std::endl;
|
||||
#endif
|
||||
return boost::report_errors();
|
||||
}
|
Reference in New Issue
Block a user