add automatic hash function creation

This commit is contained in:
fiesh
2014-07-24 14:22:55 +02:00
parent 10d363837a
commit f7685b1194
10 changed files with 297 additions and 0 deletions

View File

@ -1,6 +1,7 @@
[/==============================================================================
Copyright (C) 2001-2011 Joel de Guzman
Copyright (C) 2006 Dan Marsden
Copyright (C) 2014 Christoph Weiss
Use, modification and distribution is subject to the Boost Software
License, Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
@ -1896,6 +1897,87 @@ compile time error.
[endsect]
[section Hashing]
Automatically create a [classref boost::hash] conforming `hash_value` function.
[heading Synopsis]
template <typename Seq>
std::size_t
hash_value(Seq const& seq);
[heading Parameters]
[table
[[Parameter] [Requirement] [Description]]
[[`seq`] [Instance of __sequence__] [__sequence__ to compute hash value of]]
]
[*Return type]: `std::size_t`
[*Requirements]:
For each element `e` in sequence `seq`, `hash_value(seq)` is a valid expression
returning a type that is convertible to `std::size_t`.
[*Semantics]: Returns a combined hash value for all elements of `seq`.
[heading Header]
#include <boost/fusion/sequence/hash.hpp>
#include <boost/fusion/include/hash.hpp>
[heading Example]
#include <boost/fusion/include/equal_to.hpp>
#include <boost/fusion/include/hash.hpp>
#include <boost/fusion/include/vector.hpp>
#include <boost/unordered_map.hpp>
void foo()
{
typedef boost::fusion::vector<int, std::string, char> Vec;
const Vec v = {42, "Hello World", 't'};
// Compute a hash value directly.
std::cout << "hash_value(v) = " << boost::fusion::hash_value(v) << '\n';
// Or use it to create an unordered_map.
boost::unordered_map<Vec, bool> map;
map[v] = true;
assert(map.size() == 1 && map.count(v) == 1);
}
[heading Example]
#include <boost/fusion/include/define_struct.hpp>
#include <boost/fusion/include/equal_to.hpp>
#include <boost/fusion/include/hash.hpp>
#include <boost/unordered_set.hpp>
// We would like to define a struct that we can form unordered_sets of.
BOOST_FUSION_DEFINE_STRUCT(
(demo), Key,
(bool, b)
(std::string, s)
(int, i)
)
namespace demo {
// Make operator== and hash_value ADL accessible.
using boost::fusion::operator==;
using boost::fusion::hash_value;
typedef boost::unordered_set<demo::Key> Set;
}
void foo()
{
demo::Set set;
demo::Key key;
assert(set.count(key) == 0);
}
[endsect]
[endsect]
[endsect]

View File

@ -0,0 +1,12 @@
/*=============================================================================
Copyright (c) 2014 Christoph Weiss
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)
==============================================================================*/
#if !defined(FUSION_INCLUDE_HASH)
#define FUSION_INCLUDE_HASH
#include <boost/fusion/sequence/hash.hpp>
#endif

View File

@ -0,0 +1,42 @@
/*=============================================================================
Copyright (c) 2014 Christoph Weiss
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)
==============================================================================*/
#if !defined(FUSION_HASH_23072014_1017)
#define FUSION_HASH_23072014_1017
#include <boost/functional/hash.hpp>
#include <boost/fusion/algorithm/iteration/fold.hpp>
#include <boost/fusion/support/is_sequence.hpp>
#include <boost/utility/enable_if.hpp>
namespace boost { namespace fusion
{
namespace hashing
{
struct hash_combine_fold
{
typedef std::size_t result_type;
template<typename T>
inline std::size_t operator()(std::size_t seed, T const& v)
{
boost::hash_combine(seed, v);
return seed;
}
};
template <typename Seq>
inline typename
boost::enable_if<traits::is_sequence<Seq>, std::size_t>::type
hash_value(Seq const& seq)
{
return fold(seq, 0, hash_combine_fold());
}
}
using hashing::hash_value;
}}
#endif

View File

@ -63,6 +63,7 @@ project
[ run sequence/boost_tuple.cpp : : : : ]
[ run sequence/cons.cpp : : : : ]
[ run sequence/filter_view.cpp : : : : ]
[ run sequence/hash.cpp : : : : ]
[ run sequence/io.cpp : : : : ]
[ run sequence/iterator_range.cpp : : : : ]
[ run sequence/joint_view.cpp : : : : ]
@ -70,6 +71,7 @@ project
[ run sequence/list_construction.cpp : : : : ]
[ run sequence/list_copy.cpp : : : : ]
[ run sequence/list_iterator.cpp : : : : ]
[ run sequence/list_hash.cpp : : : : ]
[ run sequence/list_make.cpp : : : : ]
[ run sequence/list_misc.cpp : : : : ]
[ run sequence/list_mutate.cpp : : : : ]
@ -79,6 +81,7 @@ project
[ run sequence/deque_construction.cpp : : : : ]
[ run sequence/deque_copy.cpp : : : : ]
[ run sequence/deque_iterator.cpp : : : : ]
[ run sequence/deque_hash.cpp : : : : ]
[ run sequence/deque_make.cpp : : : : ]
[ run sequence/deque_misc.cpp : : : : ]
[ run sequence/deque_move.cpp : : : : ]
@ -112,6 +115,7 @@ project
[ run sequence/tuple_make.cpp : : : : ]
[ run sequence/tuple_misc.cpp : : : : ]
[ run sequence/tuple_mutate.cpp : : : : ]
[ run sequence/tuple_hash.cpp : : : : ]
[ run sequence/tuple_tie.cpp : : : : ]
[ run sequence/tr1_tuple_auto_conv.cpp : : : : ]
[ run sequence/transform_view.cpp : : : : ]
@ -124,6 +128,7 @@ project
[ run sequence/vector_move.cpp : : : : ]
[ run sequence/vector_mutate.cpp : : : : ]
[ run sequence/vector_n.cpp : : : : ]
[ run sequence/vector_hash.cpp : : : : ]
[ run sequence/vector_tie.cpp : : : : ]
[ run sequence/vector_value_at.cpp : : : : ]
[ run sequence/zip_view.cpp : : : : ]

View File

@ -0,0 +1,16 @@
/*=============================================================================
Copyright (c) 2014 Christoph Weiss
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/fusion/container/deque/deque.hpp>
#define FUSION_SEQUENCE deque
#include "hash.hpp"
int main()
{
hash_test();
return boost::report_errors();
}

58
test/sequence/hash.cpp Normal file
View File

@ -0,0 +1,58 @@
/*=============================================================================
Copyright (c) 2014 Christoph Weiss
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 <string>
#include <boost/detail/lightweight_test.hpp>
#include <boost/fusion/include/adapt_struct.hpp>
#include <boost/fusion/sequence/hash.hpp>
struct test_struct
{
test_struct(bool bb, int ii, char cc, std::string const& ss) :
b(bb),
i(ii),
c(cc),
s(ss) {}
bool b;
int i;
char c;
std::string s;
};
BOOST_FUSION_ADAPT_STRUCT(
test_struct,
(bool, b)
(int, i)
(char, c)
(std::string, s)
)
int main()
{
using boost::fusion::hash_value;
const test_struct a0(false, 1, 'c', "Hello Nurse"),
a1(false, 1, 'c', "Hello Nurse"),
b(true, 1, 'c', "Hello Nurse"),
c(false, 0, 'c', "Hello Nurse"),
d(false, 1, 'd', "Hello Nurse"),
e(false, 1, 'c', "Hello World");
BOOST_TEST(hash_value(a0) == hash_value(a1));
BOOST_TEST(hash_value(a0) != hash_value(b));
BOOST_TEST(hash_value(a0) != hash_value(c));
BOOST_TEST(hash_value(a0) != hash_value(d));
BOOST_TEST(hash_value(a0) != hash_value(e));
BOOST_TEST(hash_value(b) != hash_value(c));
BOOST_TEST(hash_value(b) != hash_value(d));
BOOST_TEST(hash_value(b) != hash_value(d));
BOOST_TEST(hash_value(c) != hash_value(d));
BOOST_TEST(hash_value(c) != hash_value(e));
BOOST_TEST(hash_value(d) != hash_value(e));
}

34
test/sequence/hash.hpp Normal file
View File

@ -0,0 +1,34 @@
/*=============================================================================
Copyright (c) 2014 Christoph Weiss
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 <string>
#include <utility>
#include <boost/detail/lightweight_test.hpp>
#include <boost/fusion/sequence/hash.hpp>
#include <boost/functional/hash.hpp>
void
hash_test()
{
using namespace boost::fusion;
const FUSION_SEQUENCE<int, char, bool, std::string> v0(42, 'x', false, "Aurea prima");
const FUSION_SEQUENCE<int, char, bool, std::string> v1(42, 'x', false, "Aurea prima");
BOOST_TEST(hash_value(v0) == hash_value(v1));
const FUSION_SEQUENCE<int, char, bool, std::string> w(41, 'x', false, "Aurea prima");
BOOST_TEST(hash_value(w) != hash_value(v0));
const FUSION_SEQUENCE<int, char, bool, std::string> x(42, 'y', false, "Aurea prima");
BOOST_TEST(hash_value(x) != hash_value(v0));
const FUSION_SEQUENCE<int, char, bool, std::string> y(42, 'x', true, "Aurea prima");
BOOST_TEST(hash_value(y) != hash_value(v0));
const FUSION_SEQUENCE<int, char, bool, std::string> z(42, 'x', false, "quae vindice nullo");
BOOST_TEST(hash_value(z) != hash_value(v0));
}

View File

@ -0,0 +1,16 @@
/*=============================================================================
Copyright (c) 2014 Christoph Weiss
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/fusion/container/list/list.hpp>
#define FUSION_SEQUENCE list
#include "hash.hpp"
int main()
{
hash_test();
return boost::report_errors();
}

View File

@ -0,0 +1,16 @@
/*=============================================================================
Copyright (c) 2014 Christoph Weiss
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/fusion/tuple/tuple.hpp>
#define FUSION_SEQUENCE tuple
#include "hash.hpp"
int main()
{
hash_test();
return boost::report_errors();
}

View File

@ -0,0 +1,16 @@
/*=============================================================================
Copyright (c) 2014 Christoph Weiss
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/fusion/container/vector/vector.hpp>
#define FUSION_SEQUENCE vector
#include "hash.hpp"
int main()
{
hash_test();
return boost::report_errors();
}