forked from boostorg/container_hash
std::variant, std::monostate support
This commit is contained in:
@@ -85,6 +85,9 @@
|
||||
# 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)
|
||||
@@ -95,6 +98,10 @@
|
||||
# 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
|
||||
@@ -103,6 +110,10 @@
|
||||
# include <optional>
|
||||
#endif
|
||||
|
||||
#if BOOST_HASH_HAS_VARIANT
|
||||
# include <variant>
|
||||
#endif
|
||||
|
||||
namespace boost
|
||||
{
|
||||
namespace hash_detail
|
||||
@@ -235,6 +246,12 @@ namespace boost
|
||||
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
|
||||
@@ -499,6 +516,21 @@ namespace boost
|
||||
}
|
||||
#endif
|
||||
|
||||
#if BOOST_HASH_HAS_VARIANT
|
||||
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)
|
||||
{
|
||||
@@ -631,6 +663,12 @@ namespace boost
|
||||
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
|
||||
|
@@ -44,6 +44,7 @@ test-suite container_hash/hash
|
||||
[ 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 ]
|
||||
|
@@ -85,6 +85,10 @@ int main() {
|
||||
<< 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
|
||||
|
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 v.value; }
|
||||
};
|
||||
|
||||
struct custom2 {
|
||||
int value;
|
||||
friend std::size_t hash_value(custom2 v) { return 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