diff --git a/.appveyor.yml b/.appveyor.yml new file mode 100644 index 0000000..76189c2 --- /dev/null +++ b/.appveyor.yml @@ -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% diff --git a/.travis.yml b/.travis.yml index 21f9e8f..644cb20 100644 --- a/.travis.yml +++ b/.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 diff --git a/include/boost/container_hash/hash/detail/float_functions.hpp b/include/boost/container_hash/detail/float_functions.hpp similarity index 100% rename from include/boost/container_hash/hash/detail/float_functions.hpp rename to include/boost/container_hash/detail/float_functions.hpp diff --git a/include/boost/container_hash/hash/detail/hash_float.hpp b/include/boost/container_hash/detail/hash_float.hpp similarity index 98% rename from include/boost/container_hash/hash/detail/hash_float.hpp rename to include/boost/container_hash/detail/hash_float.hpp index d0f7f55..f763428 100644 --- a/include/boost/container_hash/hash/detail/hash_float.hpp +++ b/include/boost/container_hash/detail/hash_float.hpp @@ -11,8 +11,8 @@ #pragma once #endif -#include -#include +#include +#include #include #include #include diff --git a/include/boost/container_hash/hash/detail/limits.hpp b/include/boost/container_hash/detail/limits.hpp similarity index 100% rename from include/boost/container_hash/hash/detail/limits.hpp rename to include/boost/container_hash/detail/limits.hpp diff --git a/include/boost/container_hash/hash/extensions.hpp b/include/boost/container_hash/extensions.hpp similarity index 99% rename from include/boost/container_hash/hash/extensions.hpp rename to include/boost/container_hash/extensions.hpp index d8e34db..393b702 100644 --- a/include/boost/container_hash/hash/extensions.hpp +++ b/include/boost/container_hash/extensions.hpp @@ -18,7 +18,7 @@ #pragma once #endif -#include +#include #include #include #include diff --git a/include/boost/container_hash/hash.hpp b/include/boost/container_hash/hash.hpp index 4a06833..76de793 100644 --- a/include/boost/container_hash/hash.hpp +++ b/include/boost/container_hash/hash.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 +// 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 +#include +#include +#include +#include +#include +#include +#include +#include + +#if defined(BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION) +#include +#endif + +#if !defined(BOOST_NO_CXX11_HDR_TYPEINDEX) +#include +#endif + +#if !defined(BOOST_NO_CXX11_HDR_SYSTEM_ERROR) +#include +#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() +# define BOOST_HASH_HAS_STRING_VIEW 1 +# endif +# if !defined(BOOST_HASH_HAS_OPTIONAL) && __has_include() +# define BOOST_HASH_HAS_OPTIONAL 1 +# endif +# if !defined(BOOST_HASH_HAS_VARIANT) && __has_include() +# 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 +#endif + +#if BOOST_HASH_HAS_OPTIONAL +# include +#endif + +#if BOOST_HASH_HAS_VARIANT +# include +#endif + +namespace boost +{ + namespace hash_detail + { +#if defined(_HAS_AUTO_PTR_ETC) && !_HAS_AUTO_PTR_ETC + template + struct hash_base + { + typedef T argument_type; + typedef std::size_t result_type; + }; +#else + template + struct hash_base : std::unary_function {}; +#endif + + struct enable_hash_value { typedef std::size_t type; }; + + template struct basic_numbers {}; + template struct long_numbers; + template struct ulong_numbers; + template struct float_numbers {}; + + template <> struct basic_numbers : + boost::hash_detail::enable_hash_value {}; + template <> struct basic_numbers : + boost::hash_detail::enable_hash_value {}; + template <> struct basic_numbers : + boost::hash_detail::enable_hash_value {}; + template <> struct basic_numbers : + boost::hash_detail::enable_hash_value {}; + template <> struct basic_numbers : + boost::hash_detail::enable_hash_value {}; + template <> struct basic_numbers : + boost::hash_detail::enable_hash_value {}; + template <> struct basic_numbers : + boost::hash_detail::enable_hash_value {}; + template <> struct basic_numbers : + boost::hash_detail::enable_hash_value {}; + template <> struct basic_numbers : + boost::hash_detail::enable_hash_value {}; + template <> struct basic_numbers : + boost::hash_detail::enable_hash_value {}; + +#if !defined(BOOST_NO_INTRINSIC_WCHAR_T) + template <> struct basic_numbers : + boost::hash_detail::enable_hash_value {}; +#endif + +#if !defined(BOOST_NO_CXX11_CHAR16_T) + template <> struct basic_numbers : + boost::hash_detail::enable_hash_value {}; +#endif + +#if !defined(BOOST_NO_CXX11_CHAR32_T) + template <> struct basic_numbers : + 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 struct long_numbers2 {}; + template struct ulong_numbers2 {}; + template struct long_numbers : long_numbers2 {}; + template struct ulong_numbers : ulong_numbers2 {}; + +#if !defined(BOOST_NO_LONG_LONG) + template <> struct long_numbers : + boost::hash_detail::enable_hash_value {}; + template <> struct ulong_numbers : + boost::hash_detail::enable_hash_value {}; +#endif + +#if defined(BOOST_HAS_INT128) + template <> struct long_numbers2 : + boost::hash_detail::enable_hash_value {}; + template <> struct ulong_numbers2 : + boost::hash_detail::enable_hash_value {}; +#endif + + template <> struct float_numbers : + boost::hash_detail::enable_hash_value {}; + template <> struct float_numbers : + boost::hash_detail::enable_hash_value {}; + template <> struct float_numbers : + boost::hash_detail::enable_hash_value {}; + } + + template + typename boost::hash_detail::basic_numbers::type hash_value(T); + template + typename boost::hash_detail::long_numbers::type hash_value(T); + template + typename boost::hash_detail::ulong_numbers::type hash_value(T); + + template + typename boost::enable_if, std::size_t>::type + hash_value(T); + +#if !BOOST_WORKAROUND(__DMC__, <= 0x848) + template std::size_t hash_value(T* const&); +#else + template 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 + std::size_t hash_value( + std::basic_string, A> const&); + +#if BOOST_HASH_HAS_STRING_VIEW + template + std::size_t hash_value( + std::basic_string_view > const&); +#endif + + template + typename boost::hash_detail::float_numbers::type hash_value(T); + +#if BOOST_HASH_HAS_OPTIONAL + template + std::size_t hash_value(std::optional const&); +#endif + +#if BOOST_HASH_HAS_VARIANT + std::size_t hash_value(std::monostate); + template + std::size_t hash_value(std::variant 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 + inline std::size_t hash_value_signed(T val) + { + const unsigned int size_t_bits = std::numeric_limits::digits; + // ceiling(std::numeric_limits::digits / size_t_bits) - 1 + const int length = (std::numeric_limits::digits - 1) + / static_cast(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 + inline std::size_t hash_value_unsigned(T val) + { + const unsigned int size_t_bits = std::numeric_limits::digits; + // ceiling(std::numeric_limits::digits / size_t_bits) - 1 + const int length = (std::numeric_limits::digits - 1) + / static_cast(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 + 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 boost::hash_detail::basic_numbers::type hash_value(T v) + { + return static_cast(v); + } + + template + typename boost::hash_detail::long_numbers::type hash_value(T v) + { + return hash_detail::hash_value_signed(v); + } + + template + typename boost::hash_detail::ulong_numbers::type hash_value(T v) + { + return hash_detail::hash_value_unsigned(v); + } + + template + typename boost::enable_if, std::size_t>::type + hash_value(T v) + { + return static_cast(v); + } + + // Implementation by Alberto Barbati and Dave Harris. +#if !BOOST_WORKAROUND(__DMC__, <= 0x848) + template std::size_t hash_value(T* const& v) +#else + template 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( + reinterpret_cast(v)); +#else + std::size_t x = static_cast( + reinterpret_cast(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 + inline void hash_combine(std::size_t& seed, T const& v) + { + boost::hash hasher; + return boost::hash_detail::hash_combine_impl(seed, hasher(v)); + } + +#if defined(BOOST_MSVC) +#pragma warning(pop) +#endif + + template + 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 + 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 + inline std::size_t hash_range(T* first, T* last) + { + std::size_t seed = 0; + + for(; first != last; ++first) + { + boost::hash hasher; + seed ^= hasher(*first) + 0x9e3779b9 + (seed<<6) + (seed>>2); + } + + return seed; + } + + template + inline void hash_range(std::size_t& seed, T* first, T* last) + { + for(; first != last; ++first) + { + boost::hash 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 + inline std::size_t hash_value( + std::basic_string, A> const& v) + { + return hash_range(v.begin(), v.end()); + } + +#if BOOST_HASH_HAS_STRING_VIEW + template + inline std::size_t hash_value( + std::basic_string_view > const& v) + { + return hash_range(v.begin(), v.end()); + } +#endif + + template + typename boost::hash_detail::float_numbers::type hash_value(T v) + { + return boost::hash_detail::float_hash_value(v); + } + +#if BOOST_HASH_HAS_OPTIONAL + template + inline std::size_t hash_value(std::optional const& v) { + if (!v) { + // Arbitray value for empty optional. + return 0x12345678; + } else { + boost::hash hf; + return hf(*v); + } + } +#endif + +#if BOOST_HASH_HAS_VARIANT + inline std::size_t hash_value(std::monostate) { + return 0x87654321; + } + + template + inline std::size_t hash_value(std::variant 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 \ + : public boost::hash_detail::hash_base \ + { \ + std::size_t operator()(type v) const \ + { \ + return boost::hash_value(v); \ + } \ + }; + +#define BOOST_HASH_SPECIALIZE_REF(type) \ + template <> struct hash \ + : public boost::hash_detail::hash_base \ + { \ + std::size_t operator()(type const& v) const \ + { \ + return boost::hash_value(v); \ + } \ + }; + +#define BOOST_HASH_SPECIALIZE_TEMPLATE_REF(type) \ + struct hash \ + : public boost::hash_detail::hash_base \ + { \ + 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) +#endif +#if !defined(BOOST_NO_CXX11_CHAR32_T) + BOOST_HASH_SPECIALIZE_REF(std::basic_string) +#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) +# endif +# if !defined(BOOST_NO_CXX11_CHAR32_T) + BOOST_HASH_SPECIALIZE_REF(std::basic_string_view) +# 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 + BOOST_HASH_SPECIALIZE_TEMPLATE_REF(std::optional) +#endif + +#if !defined(BOOST_HASH_HAS_VARIANT) + template + BOOST_HASH_SPECIALIZE_TEMPLATE_REF(std::variant) + 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 + struct hash + : public boost::hash_detail::hash_base + { + 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( + reinterpret_cast(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 + struct hash_impl; + + template <> + struct hash_impl + { + template + struct inner + : public boost::hash_detail::hash_base + { + 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( + reinterpret_cast(val)); + + return x + (x >> 3); +#endif + } + }; + }; + } + + template struct hash + : public boost::hash_detail::hash_impl::value> + ::BOOST_NESTED_TEMPLATE inner + { + }; + +#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 +#endif diff --git a/include/boost/container_hash/hash/hash.hpp b/include/boost/container_hash/hash/hash.hpp deleted file mode 100644 index 21296f3..0000000 --- a/include/boost/container_hash/hash/hash.hpp +++ /dev/null @@ -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 -#include -#include -#include -#include -#include -#include -#include -#include - -#if defined(BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION) -#include -#endif - -#if !defined(BOOST_NO_CXX11_HDR_TYPEINDEX) -#include -#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 - struct hash_base - { - typedef T argument_type; - typedef std::size_t result_type; - }; -#else - template - struct hash_base : std::unary_function {}; -#endif - - struct enable_hash_value { typedef std::size_t type; }; - - template struct basic_numbers {}; - template struct long_numbers; - template struct ulong_numbers; - template struct float_numbers {}; - - template <> struct basic_numbers : - boost::hash_detail::enable_hash_value {}; - template <> struct basic_numbers : - boost::hash_detail::enable_hash_value {}; - template <> struct basic_numbers : - boost::hash_detail::enable_hash_value {}; - template <> struct basic_numbers : - boost::hash_detail::enable_hash_value {}; - template <> struct basic_numbers : - boost::hash_detail::enable_hash_value {}; - template <> struct basic_numbers : - boost::hash_detail::enable_hash_value {}; - template <> struct basic_numbers : - boost::hash_detail::enable_hash_value {}; - template <> struct basic_numbers : - boost::hash_detail::enable_hash_value {}; - template <> struct basic_numbers : - boost::hash_detail::enable_hash_value {}; - template <> struct basic_numbers : - boost::hash_detail::enable_hash_value {}; - -#if !defined(BOOST_NO_INTRINSIC_WCHAR_T) - template <> struct basic_numbers : - boost::hash_detail::enable_hash_value {}; -#endif - -#if !defined(BOOST_NO_CXX11_CHAR16_T) - template <> struct basic_numbers : - boost::hash_detail::enable_hash_value {}; -#endif - -#if !defined(BOOST_NO_CXX11_CHAR32_T) - template <> struct basic_numbers : - 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 struct long_numbers2 {}; - template struct ulong_numbers2 {}; - template struct long_numbers : long_numbers2 {}; - template struct ulong_numbers : ulong_numbers2 {}; - -#if !defined(BOOST_NO_LONG_LONG) - template <> struct long_numbers : - boost::hash_detail::enable_hash_value {}; - template <> struct ulong_numbers : - boost::hash_detail::enable_hash_value {}; -#endif - -#if defined(BOOST_HAS_INT128) - template <> struct long_numbers2 : - boost::hash_detail::enable_hash_value {}; - template <> struct ulong_numbers2 : - boost::hash_detail::enable_hash_value {}; -#endif - - template <> struct float_numbers : - boost::hash_detail::enable_hash_value {}; - template <> struct float_numbers : - boost::hash_detail::enable_hash_value {}; - template <> struct float_numbers : - boost::hash_detail::enable_hash_value {}; - } - - template - typename boost::hash_detail::basic_numbers::type hash_value(T); - template - typename boost::hash_detail::long_numbers::type hash_value(T); - template - typename boost::hash_detail::ulong_numbers::type hash_value(T); - - template - typename boost::enable_if, std::size_t>::type - hash_value(T); - -#if !BOOST_WORKAROUND(__DMC__, <= 0x848) - template std::size_t hash_value(T* const&); -#else - template 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 - std::size_t hash_value( - std::basic_string, A> const&); - - template - typename boost::hash_detail::float_numbers::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 - inline std::size_t hash_value_signed(T val) - { - const unsigned int size_t_bits = std::numeric_limits::digits; - // ceiling(std::numeric_limits::digits / size_t_bits) - 1 - const int length = (std::numeric_limits::digits - 1) - / static_cast(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 - inline std::size_t hash_value_unsigned(T val) - { - const unsigned int size_t_bits = std::numeric_limits::digits; - // ceiling(std::numeric_limits::digits / size_t_bits) - 1 - const int length = (std::numeric_limits::digits - 1) - / static_cast(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 - 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 boost::hash_detail::basic_numbers::type hash_value(T v) - { - return static_cast(v); - } - - template - typename boost::hash_detail::long_numbers::type hash_value(T v) - { - return hash_detail::hash_value_signed(v); - } - - template - typename boost::hash_detail::ulong_numbers::type hash_value(T v) - { - return hash_detail::hash_value_unsigned(v); - } - - template - typename boost::enable_if, std::size_t>::type - hash_value(T v) - { - return static_cast(v); - } - - // Implementation by Alberto Barbati and Dave Harris. -#if !BOOST_WORKAROUND(__DMC__, <= 0x848) - template std::size_t hash_value(T* const& v) -#else - template 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( - reinterpret_cast(v)); -#else - std::size_t x = static_cast( - reinterpret_cast(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 - inline void hash_combine(std::size_t& seed, T const& v) - { - boost::hash hasher; - return boost::hash_detail::hash_combine_impl(seed, hasher(v)); - } - -#if defined(BOOST_MSVC) -#pragma warning(pop) -#endif - - template - 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 - 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 - inline std::size_t hash_range(T* first, T* last) - { - std::size_t seed = 0; - - for(; first != last; ++first) - { - boost::hash hasher; - seed ^= hasher(*first) + 0x9e3779b9 + (seed<<6) + (seed>>2); - } - - return seed; - } - - template - inline void hash_range(std::size_t& seed, T* first, T* last) - { - for(; first != last; ++first) - { - boost::hash 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 - inline std::size_t hash_value( - std::basic_string, A> const& v) - { - return hash_range(v.begin(), v.end()); - } - - template - typename boost::hash_detail::float_numbers::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 \ - : public boost::hash_detail::hash_base \ - { \ - std::size_t operator()(type v) const \ - { \ - return boost::hash_value(v); \ - } \ - }; - -#define BOOST_HASH_SPECIALIZE_REF(type) \ - template <> struct hash \ - : public boost::hash_detail::hash_base \ - { \ - 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) -#endif -#if !defined(BOOST_NO_CXX11_CHAR32_T) - BOOST_HASH_SPECIALIZE_REF(std::basic_string) -#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 - struct hash - : public boost::hash_detail::hash_base - { - 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( - reinterpret_cast(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 - struct hash_impl; - - template <> - struct hash_impl - { - template - struct inner - : public boost::hash_detail::hash_base - { - 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( - reinterpret_cast(val)); - - return x + (x >> 3); -#endif - } - }; - }; - } - - template struct hash - : public boost::hash_detail::hash_impl::value> - ::BOOST_NESTED_TEMPLATE inner - { - }; - -#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 -#endif diff --git a/include/boost/container_hash/hash/hash_fwd.hpp b/include/boost/container_hash/hash/hash_fwd.hpp deleted file mode 100644 index a87c182..0000000 --- a/include/boost/container_hash/hash/hash_fwd.hpp +++ /dev/null @@ -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 -#include - -#if defined(BOOST_HAS_PRAGMA_ONCE) -#pragma once -#endif - - -namespace boost -{ - template struct hash; - - template void hash_combine(std::size_t& seed, T const& v); - - template std::size_t hash_range(It, It); - template void hash_range(std::size_t&, It, It); - -#if BOOST_WORKAROUND(__BORLANDC__, BOOST_TESTED_AT(0x551)) - template inline std::size_t hash_range(T*, T*); - template inline void hash_range(std::size_t&, T*, T*); -#endif -} - -#endif diff --git a/include/boost/container_hash/hash_fwd.hpp b/include/boost/container_hash/hash_fwd.hpp index 5ff4801..a87c182 100644 --- a/include/boost/container_hash/hash_fwd.hpp +++ b/include/boost/container_hash/hash_fwd.hpp @@ -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 +// 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 +#include + #if defined(BOOST_HAS_PRAGMA_ONCE) #pragma once #endif -#include + +namespace boost +{ + template struct hash; + + template void hash_combine(std::size_t& seed, T const& v); + + template std::size_t hash_range(It, It); + template void hash_range(std::size_t&, It, It); + +#if BOOST_WORKAROUND(__BORLANDC__, BOOST_TESTED_AT(0x551)) + template inline std::size_t hash_range(T*, T*); + template inline void hash_range(std::size_t&, T*, T*); +#endif +} + +#endif diff --git a/include/boost/functional/hash.hpp b/include/boost/functional/hash.hpp index 6122b35..327a3ec 100644 --- a/include/boost/functional/hash.hpp +++ b/include/boost/functional/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 +#include diff --git a/include/boost/functional/hash/extensions.hpp b/include/boost/functional/hash/extensions.hpp index bd436fb..ab14211 100644 --- a/include/boost/functional/hash/extensions.hpp +++ b/include/boost/functional/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 +#include diff --git a/include/boost/functional/hash/hash.hpp b/include/boost/functional/hash/hash.hpp index 6122b35..327a3ec 100644 --- a/include/boost/functional/hash/hash.hpp +++ b/include/boost/functional/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 +#include diff --git a/include/boost/functional/hash/hash_fwd.hpp b/include/boost/functional/hash/hash_fwd.hpp index aeffad0..62bc23c 100644 --- a/include/boost/functional/hash/hash_fwd.hpp +++ b/include/boost/functional/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 +#include diff --git a/include/boost/functional/hash_fwd.hpp b/include/boost/functional/hash_fwd.hpp index aeffad0..62bc23c 100644 --- a/include/boost/functional/hash_fwd.hpp +++ b/include/boost/functional/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 +#include diff --git a/test/Jamfile.v2 b/test/Jamfile.v2 index dd2b977..a9dddfb 100644 --- a/test/Jamfile.v2 +++ b/test/Jamfile.v2 @@ -20,6 +20,7 @@ project hash-tests test-suite container_hash/hash : + [ run hash_info.cpp : : : 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 ] diff --git a/test/compile_time.hpp b/test/compile_time.hpp index db6bc59..d7631b8 100644 --- a/test/compile_time.hpp +++ b/test/compile_time.hpp @@ -5,14 +5,16 @@ #include #include -#include +#include template 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, BOOST_HASH_TEST_NAMESPACE::hash >::value)); -#endif + BOOST_STATIC_ASSERT((boost::is_same::argument_type + >::value)); + BOOST_STATIC_ASSERT((boost::is_same::result_type + >::value)); } diff --git a/test/extensions_hpp_test.cpp b/test/extensions_hpp_test.cpp index 54d1054..a388c23 100644 --- a/test/extensions_hpp_test.cpp +++ b/test/extensions_hpp_test.cpp @@ -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 +#include int main() { int x[2] = { 2, 3 }; diff --git a/test/hash_float_test.hpp b/test/hash_float_test.hpp index a73c31f..ab79a12 100644 --- a/test/hash_float_test.hpp +++ b/test/hash_float_test.hpp @@ -14,8 +14,8 @@ #include #include -#include -#include +#include +#include #include #include diff --git a/test/hash_info.cpp b/test/hash_info.cpp new file mode 100644 index 0000000..34378f5 --- /dev/null +++ b/test/hash_info.cpp @@ -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 +#include +#include + +#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 " << std::endl; +#else + std::cout << "" << std::endl; +#endif + +#if defined(BOOST_NO_CXX11_HDR_SYSTEM_ERROR) + std::cout << "No " << std::endl; +#else + std::cout << "" << std::endl; +#endif + +} diff --git a/test/hash_number_test.cpp b/test/hash_number_test.cpp index c78783e..72ab626 100644 --- a/test/hash_number_test.cpp +++ b/test/hash_number_test.cpp @@ -14,7 +14,7 @@ #include #include -#include +#include #include #include "./compile_time.hpp" diff --git a/test/hash_optional_test.cpp b/test/hash_optional_test.cpp new file mode 100644 index 0000000..4469395 --- /dev/null +++ b/test/hash_optional_test.cpp @@ -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 +#endif +#include +#include + +#if BOOST_HASH_HAS_OPTIONAL + +#include +#include + +void test_optional_int() +{ + std::optional x1a; + std::optional x1b; + std::optional x2a(10); + std::optional x2b(x2a); + std::optional x3(20); + + boost::hash > 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 x1a; + std::optional x1b; + std::optional x2a("10"); + std::optional x2b(x2a); + std::optional x3("20"); + + boost::hash > 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 << " not available." << std::endl; +#endif + return boost::report_errors(); +} diff --git a/test/hash_string_test.cpp b/test/hash_string_test.cpp index f84eb74..712c639 100644 --- a/test/hash_string_test.cpp +++ b/test/hash_string_test.cpp @@ -130,6 +130,37 @@ void u32string_tests() } #endif +template +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 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(); } diff --git a/test/hash_system_error_test.cpp b/test/hash_system_error_test.cpp new file mode 100644 index 0000000..14228d1 --- /dev/null +++ b/test/hash_system_error_test.cpp @@ -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 +#endif +#include +#include + +#if !defined(BOOST_NO_CXX11_HDR_SYSTEM_ERROR) + +#include + +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 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 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 << " not available." << std::endl; +#endif + return boost::report_errors(); +} diff --git a/test/hash_variant_test.cpp b/test/hash_variant_test.cpp new file mode 100644 index 0000000..31520f4 --- /dev/null +++ b/test/hash_variant_test.cpp @@ -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 +#endif +#include +#include + +#if BOOST_HASH_HAS_VARIANT + +#include +#include + +void test_monostate() +{ + std::monostate x1; + std::monostate x2; + + boost::hash hasher; + + BOOST_TEST(hasher(x1) == hasher(x2)); +} + +void test_variant_int() +{ + std::variant x1a; + std::variant x1b; + std::variant x2a(10); + std::variant x2b(x2a); + std::variant x3(20); + + boost::hash > 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 hasher1; + boost::hash 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 variant_type; + + variant_type y11(x11); + variant_type y12(x12); + variant_type y21(x21); + variant_type y22(x22); + + boost::hash 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 << " not available." << std::endl; +#endif + return boost::report_errors(); +}