BPHash
General object hashing library for C++
test_detect.cpp
Go to the documentation of this file.
1 /*! \file
2  * \brief Testing of compile-time detection of hashing ability
3  */
4 
5 /* Copyright (c) 2016 Benjamin Pritchard <ben@bennyp.org>
6  * This file is part of the BPHash project, which is released
7  * under the BSD 3-clause license. See the LICENSE file for details
8  */
9 
10 #include "bphash/Hasher.hpp"
11 #include "bphash/types/All.hpp"
12 
13 #include <iostream>
14 #include <string>
15 
16 using namespace bphash;
17 
18 // This class has a hash member function
20 {
21  public:
22  int i;
23  std::string s;
24 
25  void hash(Hasher & h) const { h(i, s); }
26 };
27 
28 
29 // These classes aren't hashable because of the member function is malformed
31 class HashMember_BadSig1 { public: void hash(Hasher &) { } };
32 class HashMember_BadSig2 { public: void hash(const Hasher &) const { } };
33 class HashMember_BadSig3 { public: void hash(Hasher &&) const { } };
34 class HashMember_BadSig4 { public: void hash(Hasher) const { } };
35 class HashMember_BadSig5 { public: void hash(int) const { } };
36 class HashMember_BadSig6 { public: int hash(Hasher &) const { return 0; } };
37 
38 
39 // This class is hashable via a free function
40 class HashFree
41 {
42  public:
43  int i;
44  std::string s;
45 };
46 
47 static void hash_object(const HashFree & hf, Hasher & h)
48 {
49  h(hf.i, hf.s);
50 }
51 
52 
53 // These aren't hashable due to malformed free functions
54 class HashFree_BadSig0 { };
55 class HashFree_BadSig1 { };
56 class HashFree_BadSig2 { };
57 class HashFree_BadSig3 { };
58 class HashFree_BadSig4 { };
59 class HashFree_BadSig5 { };
60 
61 /////////////////////////////////////////////////////////////////////////////
62 // Some of the following fail, since the free-function detector is a little
63 // more lax in checking some types
64 /////////////////////////////////////////////////////////////////////////////
65 //static void hash_object(HashFree_BadSig0 &, Hasher &) { }
66 //static void hash_object(const HashFree_BadSig1 &, const Hasher &) { }
67 //static void hash_object(const HashFree_BadSig2 &, Hasher) { }
68 //static void hash_object(const HashFree_BadSig3 &, Hasher &&) { }
69 //static void hash_object(const HashFree_BadSig4 &, int) { }
70 //static int hash_object(const HashFree_BadSig5 &, Hasher &) { }
71 
72 
73 
74 // This class is hashable via a free function
75 template<typename T>
77 {
78  public:
79  T data;
80 };
81 
82 template<typename T>
83 void hash_object(const HashFreeTemplate<T> & hft, Hasher & h)
84 {
85  h(hft.data);
86 }
87 
88 
89 #define IS_HASHABLE(type) static_assert(is_hashable<type>::value, "Type " #type " is not hashable, but should be")
90 #define IS_NOT_HASHABLE(type) static_assert(!is_hashable<type>::value, "Type " #type " is hashable, but shouldn't be")
91 
92 int main(void)
93 {
95 
96  // Test detection of fundamental types
97  IS_HASHABLE(char);
98  IS_HASHABLE(unsigned char);
99  IS_HASHABLE(signed char);
100  IS_HASHABLE(unsigned short);
101  IS_HASHABLE(short);
102  IS_HASHABLE(unsigned int);
103  IS_HASHABLE(int);
104  IS_HASHABLE(unsigned long);
105  IS_HASHABLE(long);
106  IS_HASHABLE(unsigned long long);
107  IS_HASHABLE(long long);
108  IS_HASHABLE(float);
109  IS_HASHABLE(double);
110  IS_HASHABLE(long double);
111 
112  // Complex numbers
113  IS_HASHABLE(std::complex<char>);
114  IS_HASHABLE(std::complex<unsigned char>);
115  IS_HASHABLE(std::complex<signed char>);
116  IS_HASHABLE(std::complex<unsigned short>);
117  IS_HASHABLE(std::complex<short>);
118  IS_HASHABLE(std::complex<unsigned int>);
119  IS_HASHABLE(std::complex<int>);
120  IS_HASHABLE(std::complex<unsigned long>);
121  IS_HASHABLE(std::complex<long>);
122  IS_HASHABLE(std::complex<unsigned long long>);
123  IS_HASHABLE(std::complex<long long>);
124  IS_HASHABLE(std::complex<float>);
125  IS_HASHABLE(std::complex<double>);
126  IS_HASHABLE(std::complex<long double>);
127 
128 
129  // Pointers to fundamental types
130  IS_HASHABLE(char *);
131  IS_HASHABLE(unsigned char *);
132  IS_HASHABLE(signed char *);
133  IS_HASHABLE(unsigned short *);
134  IS_HASHABLE(short *);
135  IS_HASHABLE(unsigned int *);
136  IS_HASHABLE(int *);
137  IS_HASHABLE(unsigned long *);
138  IS_HASHABLE(long *);
139  IS_HASHABLE(unsigned long long *);
140  IS_HASHABLE(long long *);
141  IS_HASHABLE(float *);
142  IS_HASHABLE(double *);
143  IS_HASHABLE(long double *);
144 
145  // Arrays should not be hashable
146  IS_NOT_HASHABLE(char []);
147  IS_NOT_HASHABLE(unsigned char []);
148  IS_NOT_HASHABLE(signed char []);
149  IS_NOT_HASHABLE(unsigned short []);
150  IS_NOT_HASHABLE(short []);
151  IS_NOT_HASHABLE(unsigned int []);
152  IS_NOT_HASHABLE(int []);
153  IS_NOT_HASHABLE(unsigned long []);
154  IS_NOT_HASHABLE(long []);
155  IS_NOT_HASHABLE(unsigned long long []);
156  IS_NOT_HASHABLE(long long []);
157  IS_NOT_HASHABLE(float []);
158  IS_NOT_HASHABLE(double []);
159  IS_NOT_HASHABLE(long double []);
160 
161 
162  // Test a few pairs
163  static_assert(is_hashable<std::pair<int, int>>::value, "Failed test for pair");
164  static_assert(is_hashable<std::pair<const char, float>>::value, "Failed test for pair");
165  static_assert(is_hashable<std::pair<unsigned long, short>>::value, "Failed test for pair");
166  static_assert(!is_hashable<std::pair<HashMember_BadSig0, int>>::value, "Test");
167 
168 
169  static_assert(is_hashable<HashMember>::value, "Failed test for Hash Member");
170 
171  static_assert(!is_hashable<HashMember_BadSig0>::value, "Failed test for member function bad signature 0");
172  static_assert(!is_hashable<HashMember_BadSig1>::value, "Failed test for member function bad signature 1");
173  static_assert(!is_hashable<HashMember_BadSig2>::value, "Failed test for member function bad signature 2");
174  static_assert(!is_hashable<HashMember_BadSig3>::value, "Failed test for member function bad signature 3");
175  static_assert(!is_hashable<HashMember_BadSig4>::value, "Failed test for member function bad signature 4");
176  static_assert(!is_hashable<HashMember_BadSig5>::value, "Failed test for member function bad signature 5");
177  static_assert(!is_hashable<HashMember_BadSig6>::value, "Failed test for member function bad signature 6");
178 
179 
180  static_assert(is_hashable<HashFree>::value, "Failed test for free hash function");
181 
182  static_assert(!is_hashable<HashFree_BadSig0>::value, "Failed test for free function bad signature 0");
183  //static_assert(!is_hashable<HashFree_BadSig1>::value, "Failed test for free function bad signature 1");
184  static_assert(!is_hashable<HashFree_BadSig2>::value, "Failed test for free function bad signature 2");
185  static_assert(!is_hashable<HashFree_BadSig3>::value, "Failed test for free function bad signature 3");
186  static_assert(!is_hashable<HashFree_BadSig4>::value, "Failed test for free function bad signature 4");
187  //static_assert(!is_hashable<HashFree_BadSig5>::value, "Failed test for free function bad signature 5");
188 
189  static_assert(is_hashable<HashFreeTemplate<int>>::value, "Failed test for free hash function");
190  static_assert(is_hashable<HashFreeTemplate<std::string>>::value, "Failed test for free hash function");
191 
192 
193 
194  HashMember hm{123, "This is a test string\n"};
195  HashFree hf{123, "This is a test string\n"};
196  HashFreeTemplate<int> hfti{123};
197  HashFreeTemplate<std::string> hfts{"This is a test string\n"};
198 
199  HashValue hm_val = make_hash(htype, hm);
200  HashValue hf_val = make_hash(htype, hf);
201  HashValue hfti_val = make_hash(htype, hfti);
202  HashValue hfts_val = make_hash(htype, hfts);
203 
204  std::cout << "\n\n";
205  std::cout << " Hash of HashMember class: " << hash_to_string(hm_val) << "\n";
206  std::cout << " Hash of HashFree class: " << hash_to_string(hf_val) << "\n";
207  std::cout << " Hash of HashFreeTemplate<int> class: " << hash_to_string(hfti_val) << "\n";
208  std::cout << " Hash of HashFreeTemplate<string> class: " << hash_to_string(hfts_val) << "\n";
209  std::cout << " (they aren't supposed to be the same)\n";
210  std::cout << "\n\n";
211 
212 
213 
214  return 0;
215 }
216 
int hash(Hasher &) const
Definition: test_detect.cpp:36
#define IS_NOT_HASHABLE(type)
Definition: test_detect.cpp:90
int main(void)
Definition: test_detect.cpp:92
Trait class that determines if a type is hashable or not.
Definition: Detector.hpp:25
std::string hash_to_string(const HashValue &hash)
Return a string representation of a hash.
Definition: Hash.cpp:17
void hash(Hasher) const
Definition: test_detect.cpp:34
std::enable_if< is_hashable< T >::value, void >::type hash_object(const std::array< T, N > &a, Hasher &h)
Hashing of std::array.
Definition: array.hpp:20
A class that hashes objects (header)
void hash(Hasher &&) const
Definition: test_detect.cpp:33
HashValue make_hash(HashType type, const Targs &...objs)
Convenience function for hashing objects in a single function call.
Definition: Hasher.hpp:254
HashType
Type of hash to use.
Definition: Hasher.hpp:25
void hash(Hasher &h) const
Definition: test_detect.cpp:25
Class that is used to hash objects.
Definition: Hasher.hpp:78
std::string s
Definition: test_detect.cpp:23
std::vector< uint8_t > HashValue
Stores the value of a hash.
Definition: Hash.hpp:24
Default 128-bit hash.
void hash(const Hasher &) const
Definition: test_detect.cpp:32
void hash(Hasher &)
Definition: test_detect.cpp:31
std::string s
Definition: test_detect.cpp:44
void hash(int) const
Definition: test_detect.cpp:35
A convenience header that includes all the types supported by bphash.
#define IS_HASHABLE(type)
Definition: test_detect.cpp:89