forked from boostorg/container_hash
Compare commits
775 Commits
boost-1.23
...
esp-idf-co
Author | SHA1 | Date | |
---|---|---|---|
5e34bb5fae | |||
227d778c1e | |||
5ba74cd3a9 | |||
c14d3a1e2b | |||
a3cac265b1 | |||
c28d0b813b | |||
e39bf42dfc | |||
58502fddca | |||
5701dd3119 | |||
53c12550fa | |||
561cc5d010 | |||
bdf4bfe910 | |||
06e1b613f0 | |||
12be64b71e | |||
4e2811c4e1 | |||
2dc57b745f | |||
de618bf974 | |||
87c9eefe6e | |||
98bbd2ba56 | |||
08ea1677be | |||
3d3350646f | |||
884ce4b708 | |||
db1e23b611 | |||
5ddcd7c8e7 | |||
0e2e911df5 | |||
b3c9b35a13 | |||
c9c77cb104 | |||
873a60d009 | |||
b8d315fac5 | |||
e0e86a1413 | |||
866bd60dd3 | |||
6781cff622 | |||
dd605d0d1c | |||
dd172db079 | |||
e04ca1f442 | |||
0eada2ae93 | |||
943ef0ab82 | |||
14f8934bff | |||
f08204e29a | |||
7ad0365048 | |||
b3e424b650 | |||
d2986d9a64 | |||
000276988f | |||
355603c0c2 | |||
33cd0a5964 | |||
fc11122353 | |||
cb233af718 | |||
8d820ee7d0 | |||
3800d712d5 | |||
dee871f45c | |||
143a55ea3b | |||
4ab431f12f | |||
773307fe1c | |||
06db43a56a | |||
5906cba1a0 | |||
b2222c2755 | |||
6600a26460 | |||
c95e02fe85 | |||
334eac8166 | |||
21dbdb9b47 | |||
74f9abe52c | |||
37f3e6fcb7 | |||
301c76646c | |||
a67e350fd9 | |||
2d23e7e056 | |||
9bdebb3df4 | |||
e9ffeceeab | |||
4a685b2b16 | |||
8315ec2ba7 | |||
1a4888cdb4 | |||
9e938aca41 | |||
7abcf22762 | |||
dbb410b7ef | |||
cab5c6c8d7 | |||
526e4d472d | |||
fca37b0d43 | |||
0a795c62a3 | |||
4ff953b568 | |||
cfbc94b128 | |||
f0bed67909 | |||
1c27af1e2e | |||
ebac66dc1e | |||
f0e75dd010 | |||
5959103346 | |||
3c3948ccdb | |||
998d8da8c8 | |||
bdc2840738 | |||
56f790d896 | |||
355c1cd7a4 | |||
c9b2d6fc90 | |||
2424ada9f9 | |||
faea988310 | |||
64c367734d | |||
6d84f9a41b | |||
aaa1f441ac | |||
3487450f62 | |||
8f163568f4 | |||
a4cbaa95b3 | |||
6ffc99adb7 | |||
bb99a2b1ae | |||
f05e8840d2 | |||
dff8843bb2 | |||
15ae39e176 | |||
39e4a4f184 | |||
88fbad7438 | |||
0737c56fec | |||
2b9251069f | |||
a63c85007f | |||
7a29dee42a | |||
a0a6fa0616 | |||
fe66085fbc | |||
24598bd45f | |||
7f2a43226e | |||
668f28660d | |||
9348a89fb4 | |||
3f2612d36e | |||
3cf502b34c | |||
b2e3beea3f | |||
d308495a67 | |||
00c837d523 | |||
415f2fafe2 | |||
9bbedce029 | |||
2fc970b6ae | |||
4e11c855cb | |||
bd379e1a46 | |||
b201ff97a8 | |||
e89fe04479 | |||
7ce3f759ec | |||
917ac6a88a | |||
9782883434 | |||
f0ef7b8e84 | |||
21f2b5e1db | |||
b55fbc9252 | |||
a0465807c7 | |||
e03c31c9bc | |||
c4d9a95b82 | |||
5f5a5d0648 | |||
fd2781afc9 | |||
d045cf2ecb | |||
b4e4bf577f | |||
310ca091a2 | |||
e69c4c830e | |||
aaf0d2525f | |||
171c012d47 | |||
e0331c0bd4 | |||
e30bbab19f | |||
1818113f4c | |||
8a7fc581ed | |||
5048576921 | |||
5f858645a0 | |||
fd310d2706 | |||
90a0e36638 | |||
1ce57acc41 | |||
81a65eb01c | |||
9fbda1a98a | |||
62f29ea201 | |||
f054fe932f | |||
83a874ed49 | |||
59f9543c10 | |||
a6da082784 | |||
e73522f296 | |||
3e8dbcbcc5 | |||
601b8d0378 | |||
60f5e0d393 | |||
e67d20d1c3 | |||
8c9bd9eccd | |||
88d1c5c395 | |||
957818bb97 | |||
21f32243a8 | |||
9fafa9e37b | |||
cc541b71c5 | |||
d20a68efdb | |||
d45e3986f3 | |||
1e263669cb | |||
8ea85f5ad2 | |||
e01239286c | |||
17809c3cbc | |||
8963c38770 | |||
0ad83592af | |||
cb6a0246df | |||
27b2732916 | |||
4d9f438823 | |||
ddc05d17df | |||
b9ae7e7fb6 | |||
42bb81befa | |||
f81ee167c5 | |||
5c4edf4d7d | |||
b5c3b5d00a | |||
def7a785a5 | |||
3521c417b5 | |||
8b77644ea0 | |||
d41ead127d | |||
f460c21dd0 | |||
c3e070a244 | |||
9d5a16c288 | |||
e80c0c84bb | |||
c64e516518 | |||
b40b795572 | |||
8d784ed76d | |||
6ca88a8146 | |||
53fbb04e88 | |||
c7fc03d2b9 | |||
fc3e0bff4f | |||
376000169c | |||
bc09240437 | |||
dfa8fa5d91 | |||
8098c5b302 | |||
7f3a063064 | |||
d803b3bdc0 | |||
170558e4fa | |||
4a4cb9f7a4 | |||
7a6c0f20d5 | |||
8bdfb0cf90 | |||
3ee110f82c | |||
f7ad177dae | |||
955cdaed3d | |||
9c82e48bc9 | |||
1b3bed82aa | |||
6dd58674aa | |||
4a530f85d0 | |||
babb4f8f73 | |||
01b81754cf | |||
5210c845f5 | |||
4b99dbdb64 | |||
2cdf1c7d9e | |||
a489b08e27 | |||
b9c3499f45 | |||
ab9f98455a | |||
7159a86166 | |||
d0ee8e13bd | |||
98140b7373 | |||
e2d7225f57 | |||
36545f62cf | |||
618fc6d074 | |||
c2764e22a7 | |||
9148cde86f | |||
5a811f25aa | |||
b790429529 | |||
1e6cefbfeb | |||
b0ddb244be | |||
3dfdb19bfd | |||
f184dd019f | |||
0361d416b7 | |||
7838c3678f | |||
5856bff480 | |||
468516ed71 | |||
c8d8c7edd4 | |||
e76c3dc1a2 | |||
8171dbb465 | |||
99d4923496 | |||
29865a5bca | |||
8b05fd5fdf | |||
ada1369a14 | |||
4977373964 | |||
8b19e7eaa0 | |||
75ae18ef54 | |||
754d5f535e | |||
ebc607d44e | |||
549196ca7d | |||
f2761964bd | |||
41487a2e8c | |||
ca52df8a05 | |||
b39e6e96f0 | |||
8266a55b26 | |||
711b2b6d69 | |||
d888097468 | |||
23f1db7729 | |||
35ef2502d5 | |||
aa3ab0790a | |||
6c3e20ac18 | |||
97cc6fbbc1 | |||
309d17f387 | |||
928767f2bd | |||
bb2a91bf47 | |||
496bf24900 | |||
09f197abf6 | |||
582671543b | |||
6157ad5267 | |||
844d9758bd | |||
7dbc8b593f | |||
3c22fce14c | |||
b066a9c509 | |||
74603822f4 | |||
998f714f8f | |||
614feab582 | |||
999c2d5963 | |||
c3e54942e8 | |||
10c83e95d9 | |||
734eb87d2a | |||
af17fa46fb | |||
e26c102522 | |||
378007cf94 | |||
61df9052e1 | |||
dea8d12a04 | |||
1870aa9534 | |||
b1ca4cf0d4 | |||
0d6cee7e64 | |||
9dad407f06 | |||
7d148af8d2 | |||
4aec4be0ed | |||
bb8ebafca1 | |||
7e162c4f03 | |||
061e0d9d6d | |||
cc091d5d98 | |||
e5f3356742 | |||
9721f9c764 | |||
713b688159 | |||
8a8ab9ec70 | |||
13a86a7a26 | |||
0e0906b0a4 | |||
67ad8c2151 | |||
be4292842d | |||
473b1da8de | |||
8afae2e762 | |||
03380087a9 | |||
9dcc33ab1b | |||
d8adc5aa24 | |||
7f7ecfc717 | |||
dfd48ef498 | |||
a2756e75e8 | |||
9c37cd46b1 | |||
acf1f3bc48 | |||
b856e6308d | |||
b4b4a559e0 | |||
853a713cf2 | |||
043571dabf | |||
7b2f73c225 | |||
eec47991f9 | |||
f1de575546 | |||
05f16beaf0 | |||
34a6eebf7e | |||
9119b2646b | |||
12f49f7c53 | |||
0757aea7cb | |||
92fe67f714 | |||
73b507c728 | |||
330040aea9 | |||
5ebe3ad87d | |||
411ac66581 | |||
75bcfdeb36 | |||
af3a31090c | |||
dfe0ad3a60 | |||
806abd0ddf | |||
c409903f5e | |||
8ef04ed807 | |||
6be66ba092 | |||
033ef4b507 | |||
0d4c55854b | |||
18b143cad1 | |||
8bc410f571 | |||
68f0d9bc6b | |||
5611f4238e | |||
346e62f53f | |||
963d06acb8 | |||
f3229da836 | |||
441cea413d | |||
4f3265079d | |||
98953a28c7 | |||
c3d01123fa | |||
f98a942e2e | |||
9a38ebf8c3 | |||
a6f8c51afb | |||
903b1e409e | |||
eb040cb89b | |||
d92209d725 | |||
58e42260d5 | |||
56293f4313 | |||
335930c652 | |||
da096ddf8c | |||
15bc3339e2 | |||
8c0e9a2b09 | |||
664522596f | |||
cc0710b8a2 | |||
ce885af9b0 | |||
9e641187c6 | |||
7dc95d044d | |||
ad614b3d5f | |||
fc7eb28826 | |||
ed598f865e | |||
482f038837 | |||
a2e947588d | |||
982b350d71 | |||
80b88f24c1 | |||
577054de93 | |||
a98b37d12f | |||
fc3b3863b4 | |||
906f632706 | |||
afc4d6664f | |||
bbfb6fd32c | |||
38d131c158 | |||
2553a5fbdc | |||
55fac118e9 | |||
5ce1a71c84 | |||
425de7d1dd | |||
a60758dec2 | |||
f544265741 | |||
7af7c59420 | |||
733422d1b9 | |||
f3072d2023 | |||
77f856e3cf | |||
6544b32920 | |||
538b8fb95a | |||
fdc0995489 | |||
e042170fb9 | |||
316b1aa9f0 | |||
692d65d0e4 | |||
0ba3e9b282 | |||
98f0f11423 | |||
e67ee6032a | |||
6e37c616db | |||
5860602e5c | |||
5f10c2bb7e | |||
6d7a55a4f7 | |||
0ed492ba18 | |||
2734e22b50 | |||
9938fad017 | |||
4787563f96 | |||
01630b4053 | |||
78eeabaeb2 | |||
d45d471e34 | |||
3882189584 | |||
079f8025b3 | |||
b43c9fa145 | |||
b0ceeca154 | |||
d8bfb81914 | |||
9958072d2a | |||
99c6e89390 | |||
84e1b951f5 | |||
3ee9d7d507 | |||
1d792ecb45 | |||
e75f94f71d | |||
5db98a2dda | |||
58eab40c2a | |||
f9669b6218 | |||
2b3bc8c3f4 | |||
07b565143f | |||
d8980c3f09 | |||
83b052b784 | |||
c51bebf8a4 | |||
8b98036bb8 | |||
4774d24966 | |||
13f44653b5 | |||
e20c872440 | |||
600740e2ae | |||
52a964ae91 | |||
3d79c2f1e4 | |||
3cf1a67771 | |||
9cc8c20413 | |||
9f4a6a966e | |||
786af5df98 | |||
6a2d96428b | |||
15d4153c37 | |||
326a338add | |||
f6e0d26ffc | |||
e624b55a5c | |||
b0459a20da | |||
909d0c9547 | |||
912aed0b57 | |||
e5d343faea | |||
3e320b7ae5 | |||
8bc6175fa0 | |||
6751e9cf47 | |||
004e4df2a2 | |||
411f559730 | |||
8a6aba46c7 | |||
65b103e812 | |||
c160428eff | |||
dda32a279a | |||
ff7008e031 | |||
8fd93d38bb | |||
bc87281ed6 | |||
e3aa41fd38 | |||
f1a8a0fde8 | |||
0d0399df8a | |||
814476afa2 | |||
3d46f066c7 | |||
9ef99e556a | |||
2aff9855bb | |||
72cb0e7788 | |||
48ddd0570d | |||
220c3a4e62 | |||
27e69dea72 | |||
b0b7f17984 | |||
342284f4cf | |||
fe6449fea6 | |||
eb3202f6fc | |||
a3e434ec47 | |||
7c72c09288 | |||
45dfe7d9c5 | |||
2560590a2b | |||
c984bbb5f0 | |||
bef51c68a6 | |||
f01dd8b31a | |||
0480bcf503 | |||
2de255bab8 | |||
6ae2b9da78 | |||
058c541da1 | |||
bf23bd7ed3 | |||
b6a089242c | |||
d9fd6a499d | |||
cec8e80658 | |||
3e24330335 | |||
3f1cbcd762 | |||
59f9787c11 | |||
8daec229d2 | |||
838100c8fd | |||
dd0632c991 | |||
707186737c | |||
55663ad285 | |||
b9917c8810 | |||
cc8672de3e | |||
e810954b62 | |||
4bb4957dc4 | |||
b3e82db752 | |||
62226713a2 | |||
db3e4eee37 | |||
bd9c0e53d7 | |||
dd854f794b | |||
b1b9907efd | |||
55acb6d733 | |||
5b34fead70 | |||
1cc54e9d62 | |||
56714cf282 | |||
038a21dae6 | |||
110f23f6aa | |||
b2d85ea76b | |||
102c76bd98 | |||
f0f19cd688 | |||
210ed051dd | |||
06b83dbce0 | |||
7ef0748e07 | |||
3cd8ea5b60 | |||
b0d0ec44ec | |||
b59fe14895 | |||
829966aac1 | |||
035b91bdcd | |||
571d7bfd25 | |||
793b9f5eeb | |||
558f92f421 | |||
1d34150bb9 | |||
45d409c405 | |||
2e6da0ab6d | |||
74a03d1655 | |||
a93b6e3fea | |||
d83e6aef2b | |||
81a2c42496 | |||
1df7ab54e3 | |||
5194d14c25 | |||
cc8d3636e8 | |||
423d71ae31 | |||
d3719996d2 | |||
ce6543623e | |||
26dc8abf25 | |||
f637c9e8ce | |||
59f532cc68 | |||
d756415eb3 | |||
ee28cdbcd5 | |||
3b30bda727 | |||
48c2728dd5 | |||
58285d414e | |||
90c422e846 | |||
db8825c7d1 | |||
9211fcba2e | |||
f15ea62785 | |||
bd102b0479 | |||
2ae3f472c1 | |||
33643fd6b3 | |||
aa7a824c6d | |||
567290d703 | |||
59064fed23 | |||
8d271da155 | |||
4e59762347 | |||
fbe0c3eeca | |||
0728daf92d | |||
049552f71f | |||
d25ca5a376 | |||
15d9d535a9 | |||
27d2c57873 | |||
4ef5d0d98c | |||
244c6802b0 | |||
be0cd834a1 | |||
e0c13b595d | |||
5831163a21 | |||
8f08a63793 | |||
8e0e4dbb6e | |||
8241c0a087 | |||
e8970a08f3 | |||
891112a42f | |||
718fda8635 | |||
524335a091 | |||
f31d7a7613 | |||
586c98cb7e | |||
74fc58cd13 | |||
e5b0a03e57 | |||
7438a90198 | |||
555fefae20 | |||
4c24efeadf | |||
bf7e1328c4 | |||
946d693768 | |||
87a3e4f6f0 | |||
aa9670ad2f | |||
3ebd297644 | |||
c2d8b6c92e | |||
8aa2b19669 | |||
64da418fb2 | |||
a60b7d12f3 | |||
a08d42c10f | |||
9430503530 | |||
59643536dd | |||
c8845a10fb | |||
b165afccaa | |||
b81d239dbb | |||
64d717dcf5 | |||
f0176013b7 | |||
292d7a7ae5 | |||
311bf0d6c5 | |||
46654045d7 | |||
572d82713b | |||
4283c17309 | |||
8eb8ad993a | |||
d8c636ef9f | |||
82cca89876 | |||
3b947c29de | |||
fb20d59aa8 | |||
ba4c0abf5d | |||
6ee55d99e7 | |||
a4b51721db | |||
cae86235d5 | |||
81af8bc170 | |||
59adb10b3a | |||
3b29b95b8e | |||
9dd1099e28 | |||
855ebe6b69 | |||
e4b7765da1 | |||
81e3119c51 | |||
f3e6c4e96a | |||
86eae42d6f | |||
58aec4566a | |||
58033a375f | |||
9cbe356636 | |||
906f897e4a | |||
32d68419ec | |||
77ac0f4198 | |||
e1c1fc681d | |||
6caa46edab | |||
c81a6bee4e | |||
e592b7f057 | |||
da8405cb69 | |||
39570c232c | |||
7770a516fe | |||
49a87ce365 | |||
8e8f7a8d11 | |||
60d6f2fabd | |||
22a2c49db9 | |||
3ce1a740b7 | |||
d11d2dd17a | |||
17d5f71c35 | |||
a332300682 | |||
fa8ce5ac40 | |||
bbb8d4f19f | |||
59ee910b2e | |||
bf0ea56eac | |||
5fdfe5d328 | |||
3788bb9e75 | |||
b36cac82c3 | |||
4baf5e8517 | |||
946d1b9cc3 | |||
0a1800f9f8 | |||
7ec1fbe694 | |||
4bee159a10 | |||
514757c312 | |||
1cf74208aa | |||
1d5bfbcc9c | |||
5a5bbbf403 | |||
50011103a4 | |||
19564252b4 | |||
b2be632311 | |||
003ec473b6 | |||
c6f5970551 | |||
a7d8c36057 | |||
e09e3f1e06 | |||
691437839e | |||
d8328a403c | |||
946a362d56 | |||
81483cc533 | |||
b922722090 | |||
da55a4fcca | |||
e78d662c7a | |||
1f2c6bfaba | |||
79b5aa7a2e | |||
ed548575d4 | |||
af88f13aca | |||
1ff1366c5e | |||
a5d18ba409 | |||
f9a050b68e | |||
a9144ed80b | |||
4ed4e4760b | |||
332201e5c8 | |||
e225ed8f14 | |||
11170a916b | |||
26f4b6cd55 | |||
6f61ab5b0b | |||
1ec297d8d4 | |||
906b14102d | |||
803b01c8c8 | |||
016766fdec | |||
b70f0b3aab | |||
bb16ae385a | |||
f5cbe3661c | |||
9158f88562 | |||
eb20117301 | |||
379105280f | |||
1df9014b94 | |||
30bc59df59 | |||
b2c5ed9adf | |||
9a63dd6667 | |||
5e713acaef | |||
bc9ab80b9f | |||
dedb3ba27b | |||
1cea89464b | |||
74ec71fe8d | |||
8090093f06 | |||
16b4e4b261 | |||
bbf337598b | |||
386d46aff0 | |||
8b483e7d86 | |||
177884e8a3 | |||
7e6b470009 | |||
f2a59837b0 | |||
78b6d8731e | |||
7c2f3b6bf5 | |||
dd93c7c9a4 | |||
7092068156 | |||
572ec155db | |||
9a96585cb9 | |||
dbcb234320 | |||
412ec29987 | |||
d8eb578ae5 | |||
1cf16e51b9 | |||
91dfc92b0e | |||
f2afc2a08d | |||
7223c8da60 | |||
0fae4b4f65 | |||
72cd8cdaa1 | |||
43e79383ae | |||
dbed5ebafa | |||
976683836e | |||
9cd9c5780f | |||
be1be0d1fe | |||
557e8e7ff9 | |||
0a43718366 | |||
8c8baeedd8 | |||
763e59741a | |||
8b08528611 | |||
18b3a53699 | |||
a267ab6a2c | |||
477004a45d | |||
15d97d95e7 | |||
1d10a0f323 | |||
5e9f0e4c8e | |||
896e07cca7 | |||
e24a93d8c6 | |||
50e6bad2fd | |||
d252ee760d | |||
2d91127422 | |||
a65dc47fcb | |||
3d0a7a34dd | |||
d305aad29d | |||
52750a193d | |||
f3d016cf6d | |||
733ded8185 | |||
0aff6fe1a8 | |||
27d6247dac | |||
8bfc36b94d | |||
2b375867f5 |
72
.appveyor.yml
Normal file
72
.appveyor.yml
Normal file
@ -0,0 +1,72 @@
|
||||
# Copyright 2017 Daniel James
|
||||
# Copyright 2016-2021 Peter Dimov
|
||||
# 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
|
||||
|
||||
branches:
|
||||
only:
|
||||
- master
|
||||
- develop
|
||||
- /feature\/.*/
|
||||
|
||||
environment:
|
||||
matrix:
|
||||
- APPVEYOR_BUILD_WORKER_IMAGE: Visual Studio 2015
|
||||
TOOLSET: msvc-9.0,msvc-10.0,msvc-11.0
|
||||
ADDRMD: 32
|
||||
- APPVEYOR_BUILD_WORKER_IMAGE: Visual Studio 2015
|
||||
TOOLSET: msvc-12.0,msvc-14.0
|
||||
ADDRMD: 32,64
|
||||
- APPVEYOR_BUILD_WORKER_IMAGE: Visual Studio 2017
|
||||
TOOLSET: msvc-14.1
|
||||
CXXSTD: 14,17
|
||||
ADDRMD: 32,64
|
||||
- APPVEYOR_BUILD_WORKER_IMAGE: Visual Studio 2019
|
||||
TOOLSET: msvc-14.2
|
||||
CXXSTD: 14,17,latest
|
||||
ADDRMD: 32,64
|
||||
- APPVEYOR_BUILD_WORKER_IMAGE: Visual Studio 2019
|
||||
TOOLSET: clang-win
|
||||
CXXSTD: 14,17,latest
|
||||
ADDRMD: 64
|
||||
- APPVEYOR_BUILD_WORKER_IMAGE: Visual Studio 2015
|
||||
ADDPATH: C:\cygwin\bin;
|
||||
TOOLSET: gcc
|
||||
CXXSTD: 03,11,14,1z
|
||||
- APPVEYOR_BUILD_WORKER_IMAGE: Visual Studio 2015
|
||||
ADDPATH: C:\cygwin64\bin;
|
||||
TOOLSET: gcc
|
||||
CXXSTD: 03,11,14,1z
|
||||
- APPVEYOR_BUILD_WORKER_IMAGE: Visual Studio 2015
|
||||
ADDPATH: C:\mingw\bin;
|
||||
TOOLSET: gcc
|
||||
CXXSTD: 03,11,14,1z
|
||||
- APPVEYOR_BUILD_WORKER_IMAGE: Visual Studio 2015
|
||||
ADDPATH: C:\mingw-w64\x86_64-6.3.0-posix-seh-rt_v5-rev1\mingw64\bin;
|
||||
TOOLSET: gcc
|
||||
CXXSTD: 03,11,14,1z
|
||||
|
||||
install:
|
||||
- set BOOST_BRANCH=develop
|
||||
- if "%APPVEYOR_REPO_BRANCH%" == "master" set BOOST_BRANCH=master
|
||||
- cd ..
|
||||
- git clone -b %BOOST_BRANCH% --depth 1 https://github.com/boostorg/boost.git boost-root
|
||||
- cd boost-root
|
||||
- git submodule update --init tools/boostdep
|
||||
- xcopy /s /e /q %APPVEYOR_BUILD_FOLDER% libs\container_hash\
|
||||
- python tools/boostdep/depinst/depinst.py -I examples container_hash
|
||||
- cmd /c bootstrap
|
||||
- b2 -d0 headers
|
||||
|
||||
build: off
|
||||
|
||||
test_script:
|
||||
- PATH=%ADDPATH%%PATH%
|
||||
- if not "%CXXSTD%" == "" set CXXSTD=cxxstd=%CXXSTD%
|
||||
- if not "%ADDRMD%" == "" set ADDRMD=address-model=%ADDRMD%
|
||||
- b2 -j3 --verbose-test libs/container_hash/test//hash_info toolset=%TOOLSET% %CXXSTD% %ADDRMD% variant=debug,release embed-manifest-via=linker
|
||||
- b2 -j3 libs/container_hash/test toolset=%TOOLSET% %CXXSTD% %ADDRMD% variant=debug,release embed-manifest-via=linker
|
386
.github/workflows/ci.yml
vendored
Normal file
386
.github/workflows/ci.yml
vendored
Normal file
@ -0,0 +1,386 @@
|
||||
name: CI
|
||||
|
||||
on:
|
||||
pull_request:
|
||||
push:
|
||||
branches:
|
||||
- master
|
||||
- develop
|
||||
- feature/**
|
||||
|
||||
env:
|
||||
UBSAN_OPTIONS: print_stacktrace=1
|
||||
|
||||
jobs:
|
||||
posix:
|
||||
strategy:
|
||||
fail-fast: false
|
||||
matrix:
|
||||
include:
|
||||
- toolset: gcc-4.8
|
||||
cxxstd: "03,11"
|
||||
os: ubuntu-18.04
|
||||
install: g++-4.8-multilib
|
||||
address-model: 32,64
|
||||
- toolset: gcc-5
|
||||
cxxstd: "03,11,14,1z"
|
||||
os: ubuntu-18.04
|
||||
install: g++-5-multilib
|
||||
address-model: 32,64
|
||||
- toolset: gcc-6
|
||||
cxxstd: "03,11,14,1z"
|
||||
os: ubuntu-18.04
|
||||
install: g++-6-multilib
|
||||
address-model: 32,64
|
||||
- toolset: gcc-7
|
||||
cxxstd: "03,11,14,17"
|
||||
os: ubuntu-18.04
|
||||
install: g++-7-multilib
|
||||
address-model: 32,64
|
||||
- toolset: gcc-8
|
||||
cxxstd: "03,11,14,17,2a"
|
||||
os: ubuntu-18.04
|
||||
install: g++-8-multilib
|
||||
address-model: 32,64
|
||||
- toolset: gcc-9
|
||||
cxxstd: "03,11,14,17,2a"
|
||||
os: ubuntu-20.04
|
||||
install: g++-9-multilib
|
||||
address-model: 32,64
|
||||
- toolset: gcc-10
|
||||
cxxstd: "03,11,14,17,2a"
|
||||
os: ubuntu-20.04
|
||||
install: g++-10-multilib
|
||||
address-model: 32,64
|
||||
- toolset: gcc-11
|
||||
cxxstd: "03,11,14,17,20"
|
||||
os: ubuntu-20.04
|
||||
install: g++-11-multilib
|
||||
address-model: 32,64
|
||||
- toolset: gcc-12
|
||||
cxxstd: "03,11,14,17,20"
|
||||
os: ubuntu-22.04
|
||||
install: g++-12-multilib
|
||||
address-model: 32,64
|
||||
- toolset: clang
|
||||
compiler: clang++-3.9
|
||||
cxxstd: "03,11,14"
|
||||
os: ubuntu-18.04
|
||||
install: clang-3.9
|
||||
- toolset: clang
|
||||
compiler: clang++-4.0
|
||||
cxxstd: "03,11,14"
|
||||
os: ubuntu-18.04
|
||||
install: clang-4.0
|
||||
- toolset: clang
|
||||
compiler: clang++-5.0
|
||||
cxxstd: "03,11,14,1z"
|
||||
os: ubuntu-18.04
|
||||
install: clang-5.0
|
||||
- toolset: clang
|
||||
compiler: clang++-6.0
|
||||
cxxstd: "03,11,14,17"
|
||||
os: ubuntu-18.04
|
||||
install: clang-6.0
|
||||
- toolset: clang
|
||||
compiler: clang++-7
|
||||
cxxstd: "03,11,14,17"
|
||||
os: ubuntu-18.04
|
||||
install: clang-7
|
||||
- toolset: clang
|
||||
compiler: clang++-8
|
||||
cxxstd: "03,11,14,17"
|
||||
os: ubuntu-20.04
|
||||
install: clang-8
|
||||
- toolset: clang
|
||||
compiler: clang++-9
|
||||
cxxstd: "03,11,14,17,2a"
|
||||
os: ubuntu-20.04
|
||||
install: clang-9
|
||||
- toolset: clang
|
||||
compiler: clang++-10
|
||||
cxxstd: "03,11,14,17,2a"
|
||||
os: ubuntu-20.04
|
||||
- toolset: clang
|
||||
compiler: clang++-11
|
||||
cxxstd: "03,11,14,17,2a"
|
||||
os: ubuntu-20.04
|
||||
- toolset: clang
|
||||
compiler: clang++-12
|
||||
cxxstd: "03,11,14,17,20"
|
||||
os: ubuntu-20.04
|
||||
- toolset: clang
|
||||
compiler: clang++-13
|
||||
cxxstd: "03,11,14,17,20"
|
||||
os: ubuntu-22.04
|
||||
install: clang-13
|
||||
- toolset: clang
|
||||
compiler: clang++-14
|
||||
cxxstd: "03,11,14,17,20"
|
||||
os: ubuntu-22.04
|
||||
install: clang-14
|
||||
- toolset: clang
|
||||
cxxstd: "03,11,14,17,2a"
|
||||
os: macos-10.15
|
||||
|
||||
runs-on: ${{matrix.os}}
|
||||
|
||||
steps:
|
||||
- uses: actions/checkout@v2
|
||||
|
||||
- name: Install packages
|
||||
if: matrix.install
|
||||
run: sudo apt install ${{matrix.install}}
|
||||
|
||||
- name: Setup Boost
|
||||
run: |
|
||||
echo GITHUB_REPOSITORY: $GITHUB_REPOSITORY
|
||||
LIBRARY=${GITHUB_REPOSITORY#*/}
|
||||
echo LIBRARY: $LIBRARY
|
||||
echo "LIBRARY=$LIBRARY" >> $GITHUB_ENV
|
||||
echo GITHUB_BASE_REF: $GITHUB_BASE_REF
|
||||
echo GITHUB_REF: $GITHUB_REF
|
||||
REF=${GITHUB_BASE_REF:-$GITHUB_REF}
|
||||
REF=${REF#refs/heads/}
|
||||
echo REF: $REF
|
||||
BOOST_BRANCH=develop && [ "$REF" == "master" ] && BOOST_BRANCH=master || true
|
||||
echo BOOST_BRANCH: $BOOST_BRANCH
|
||||
cd ..
|
||||
git clone -b $BOOST_BRANCH --depth 1 https://github.com/boostorg/boost.git boost-root
|
||||
cd boost-root
|
||||
cp -r $GITHUB_WORKSPACE/* libs/$LIBRARY
|
||||
git submodule update --init tools/boostdep
|
||||
python tools/boostdep/depinst/depinst.py -I examples --git_args "--jobs 3" $LIBRARY
|
||||
./bootstrap.sh
|
||||
./b2 -d0 headers
|
||||
|
||||
- name: Create user-config.jam
|
||||
if: matrix.compiler
|
||||
run: |
|
||||
echo "using ${{matrix.toolset}} : : ${{matrix.compiler}} ;" > ~/user-config.jam
|
||||
|
||||
- name: Run tests
|
||||
run: |
|
||||
cd ../boost-root
|
||||
export ADDRMD=${{matrix.address-model}}
|
||||
./b2 -j3 --verbose-test libs/$LIBRARY/test//hash_info toolset=${{matrix.toolset}} cxxstd=${{matrix.cxxstd}} ${ADDRMD:+address-model=$ADDRMD} variant=debug,release
|
||||
./b2 -j3 libs/$LIBRARY/test toolset=${{matrix.toolset}} cxxstd=${{matrix.cxxstd}} ${ADDRMD:+address-model=$ADDRMD} variant=debug,release
|
||||
|
||||
windows:
|
||||
strategy:
|
||||
fail-fast: false
|
||||
matrix:
|
||||
include:
|
||||
- toolset: msvc-14.0
|
||||
cxxstd: 14,latest
|
||||
addrmd: 32,64
|
||||
os: windows-2019
|
||||
- toolset: msvc-14.2
|
||||
cxxstd: "14,17,20,latest"
|
||||
addrmd: 32,64
|
||||
os: windows-2019
|
||||
- toolset: msvc-14.3
|
||||
cxxstd: "14,17,20,latest"
|
||||
addrmd: 32,64
|
||||
os: windows-2022
|
||||
- toolset: clang-win
|
||||
cxxstd: "14,17,latest"
|
||||
addrmd: 32,64
|
||||
os: windows-2022
|
||||
- toolset: gcc
|
||||
cxxstd: "03,11,14,17,2a"
|
||||
addrmd: 64
|
||||
os: windows-2019
|
||||
|
||||
runs-on: ${{matrix.os}}
|
||||
|
||||
steps:
|
||||
- uses: actions/checkout@v2
|
||||
|
||||
- name: Setup Boost
|
||||
shell: cmd
|
||||
run: |
|
||||
echo GITHUB_REPOSITORY: %GITHUB_REPOSITORY%
|
||||
for /f %%i in ("%GITHUB_REPOSITORY%") do set LIBRARY=%%~nxi
|
||||
echo LIBRARY: %LIBRARY%
|
||||
echo LIBRARY=%LIBRARY%>>%GITHUB_ENV%
|
||||
echo GITHUB_BASE_REF: %GITHUB_BASE_REF%
|
||||
echo GITHUB_REF: %GITHUB_REF%
|
||||
if "%GITHUB_BASE_REF%" == "" set GITHUB_BASE_REF=%GITHUB_REF%
|
||||
set BOOST_BRANCH=develop
|
||||
for /f %%i in ("%GITHUB_BASE_REF%") do if "%%~nxi" == "master" set BOOST_BRANCH=master
|
||||
echo BOOST_BRANCH: %BOOST_BRANCH%
|
||||
cd ..
|
||||
git clone -b %BOOST_BRANCH% --depth 1 https://github.com/boostorg/boost.git boost-root
|
||||
cd boost-root
|
||||
xcopy /s /e /q %GITHUB_WORKSPACE% libs\%LIBRARY%\
|
||||
git submodule update --init tools/boostdep
|
||||
python tools/boostdep/depinst/depinst.py -I examples --git_args "--jobs 3" %LIBRARY%
|
||||
cmd /c bootstrap
|
||||
b2 -d0 headers
|
||||
|
||||
- name: Run tests
|
||||
shell: cmd
|
||||
run: |
|
||||
cd ../boost-root
|
||||
b2 -j3 --verbose-test libs/%LIBRARY%/test//hash_info toolset=${{matrix.toolset}} cxxstd=${{matrix.cxxstd}} address-model=${{matrix.addrmd}} variant=debug,release embed-manifest-via=linker
|
||||
b2 -j3 libs/%LIBRARY%/test toolset=${{matrix.toolset}} cxxstd=${{matrix.cxxstd}} address-model=${{matrix.addrmd}} variant=debug,release embed-manifest-via=linker
|
||||
|
||||
posix-cmake-subdir:
|
||||
strategy:
|
||||
fail-fast: false
|
||||
matrix:
|
||||
include:
|
||||
- os: ubuntu-18.04
|
||||
- os: ubuntu-20.04
|
||||
- os: ubuntu-22.04
|
||||
- os: macos-10.15
|
||||
|
||||
runs-on: ${{matrix.os}}
|
||||
|
||||
steps:
|
||||
- uses: actions/checkout@v2
|
||||
|
||||
- name: Install packages
|
||||
if: matrix.install
|
||||
run: sudo apt install ${{matrix.install}}
|
||||
|
||||
- name: Setup Boost
|
||||
run: |
|
||||
echo GITHUB_REPOSITORY: $GITHUB_REPOSITORY
|
||||
LIBRARY=${GITHUB_REPOSITORY#*/}
|
||||
echo LIBRARY: $LIBRARY
|
||||
echo "LIBRARY=$LIBRARY" >> $GITHUB_ENV
|
||||
echo GITHUB_BASE_REF: $GITHUB_BASE_REF
|
||||
echo GITHUB_REF: $GITHUB_REF
|
||||
REF=${GITHUB_BASE_REF:-$GITHUB_REF}
|
||||
REF=${REF#refs/heads/}
|
||||
echo REF: $REF
|
||||
BOOST_BRANCH=develop && [ "$REF" == "master" ] && BOOST_BRANCH=master || true
|
||||
echo BOOST_BRANCH: $BOOST_BRANCH
|
||||
cd ..
|
||||
git clone -b $BOOST_BRANCH --depth 1 https://github.com/boostorg/boost.git boost-root
|
||||
cd boost-root
|
||||
cp -r $GITHUB_WORKSPACE/* libs/$LIBRARY
|
||||
git submodule update --init tools/boostdep
|
||||
python tools/boostdep/depinst/depinst.py --git_args "--jobs 3" $LIBRARY
|
||||
|
||||
- name: Use library with add_subdirectory
|
||||
run: |
|
||||
cd ../boost-root/libs/$LIBRARY/test/cmake_subdir_test
|
||||
mkdir __build__ && cd __build__
|
||||
cmake ..
|
||||
cmake --build .
|
||||
ctest --output-on-failure --no-tests=error
|
||||
|
||||
posix-cmake-install:
|
||||
strategy:
|
||||
fail-fast: false
|
||||
matrix:
|
||||
include:
|
||||
- os: ubuntu-18.04
|
||||
- os: ubuntu-20.04
|
||||
- os: ubuntu-22.04
|
||||
- os: macos-10.15
|
||||
|
||||
runs-on: ${{matrix.os}}
|
||||
|
||||
steps:
|
||||
- uses: actions/checkout@v2
|
||||
|
||||
- name: Install packages
|
||||
if: matrix.install
|
||||
run: sudo apt install ${{matrix.install}}
|
||||
|
||||
- name: Setup Boost
|
||||
run: |
|
||||
echo GITHUB_REPOSITORY: $GITHUB_REPOSITORY
|
||||
LIBRARY=${GITHUB_REPOSITORY#*/}
|
||||
echo LIBRARY: $LIBRARY
|
||||
echo "LIBRARY=$LIBRARY" >> $GITHUB_ENV
|
||||
echo GITHUB_BASE_REF: $GITHUB_BASE_REF
|
||||
echo GITHUB_REF: $GITHUB_REF
|
||||
REF=${GITHUB_BASE_REF:-$GITHUB_REF}
|
||||
REF=${REF#refs/heads/}
|
||||
echo REF: $REF
|
||||
BOOST_BRANCH=develop && [ "$REF" == "master" ] && BOOST_BRANCH=master || true
|
||||
echo BOOST_BRANCH: $BOOST_BRANCH
|
||||
cd ..
|
||||
git clone -b $BOOST_BRANCH --depth 1 https://github.com/boostorg/boost.git boost-root
|
||||
cd boost-root
|
||||
cp -r $GITHUB_WORKSPACE/* libs/$LIBRARY
|
||||
git submodule update --init tools/boostdep
|
||||
python tools/boostdep/depinst/depinst.py --git_args "--jobs 3" $LIBRARY
|
||||
|
||||
- name: Configure
|
||||
run: |
|
||||
cd ../boost-root
|
||||
mkdir __build__ && cd __build__
|
||||
cmake -DBOOST_INCLUDE_LIBRARIES=$LIBRARY -DCMAKE_INSTALL_PREFIX=~/.local ..
|
||||
|
||||
- name: Install
|
||||
run: |
|
||||
cd ../boost-root/__build__
|
||||
cmake --build . --target install
|
||||
|
||||
- name: Use the installed library
|
||||
run: |
|
||||
cd ../boost-root/libs/$LIBRARY/test/cmake_install_test && mkdir __build__ && cd __build__
|
||||
cmake -DCMAKE_INSTALL_PREFIX=~/.local ..
|
||||
cmake --build .
|
||||
ctest --output-on-failure --no-tests=error
|
||||
|
||||
posix-cmake-test:
|
||||
strategy:
|
||||
fail-fast: false
|
||||
matrix:
|
||||
include:
|
||||
- os: ubuntu-18.04
|
||||
- os: ubuntu-20.04
|
||||
- os: ubuntu-22.04
|
||||
- os: macos-10.15
|
||||
|
||||
runs-on: ${{matrix.os}}
|
||||
|
||||
steps:
|
||||
- uses: actions/checkout@v2
|
||||
|
||||
- name: Install packages
|
||||
if: matrix.install
|
||||
run: sudo apt install ${{matrix.install}}
|
||||
|
||||
- name: Setup Boost
|
||||
run: |
|
||||
echo GITHUB_REPOSITORY: $GITHUB_REPOSITORY
|
||||
LIBRARY=${GITHUB_REPOSITORY#*/}
|
||||
echo LIBRARY: $LIBRARY
|
||||
echo "LIBRARY=$LIBRARY" >> $GITHUB_ENV
|
||||
echo GITHUB_BASE_REF: $GITHUB_BASE_REF
|
||||
echo GITHUB_REF: $GITHUB_REF
|
||||
REF=${GITHUB_BASE_REF:-$GITHUB_REF}
|
||||
REF=${REF#refs/heads/}
|
||||
echo REF: $REF
|
||||
BOOST_BRANCH=develop && [ "$REF" == "master" ] && BOOST_BRANCH=master || true
|
||||
echo BOOST_BRANCH: $BOOST_BRANCH
|
||||
cd ..
|
||||
git clone -b $BOOST_BRANCH --depth 1 https://github.com/boostorg/boost.git boost-root
|
||||
cd boost-root
|
||||
cp -r $GITHUB_WORKSPACE/* libs/$LIBRARY
|
||||
git submodule update --init tools/boostdep
|
||||
python tools/boostdep/depinst/depinst.py --git_args "--jobs 3" $LIBRARY
|
||||
|
||||
- name: Configure
|
||||
run: |
|
||||
cd ../boost-root
|
||||
mkdir __build__ && cd __build__
|
||||
cmake -DBOOST_INCLUDE_LIBRARIES=$LIBRARY -DBUILD_TESTING=ON ..
|
||||
|
||||
- name: Build tests
|
||||
run: |
|
||||
cd ../boost-root/__build__
|
||||
cmake --build . --target tests
|
||||
|
||||
- name: Run tests
|
||||
run: |
|
||||
cd ../boost-root/__build__
|
||||
ctest --output-on-failure --no-tests=error
|
78
.travis.yml
Normal file
78
.travis.yml
Normal file
@ -0,0 +1,78 @@
|
||||
# Copyright (C) 2016 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)
|
||||
|
||||
# Use Trusty to get a reasonably recent version of Boost.
|
||||
sudo: required
|
||||
dist: trusty
|
||||
|
||||
language: c++
|
||||
|
||||
matrix:
|
||||
include:
|
||||
- compiler: gcc
|
||||
env: |
|
||||
USER_CONFIG="using gcc : : g++-4.8 ;"
|
||||
CXXSTD=03,11
|
||||
- compiler: g++-7
|
||||
env: |
|
||||
USER_CONFIG="using gcc : : g++-7 ;"
|
||||
CXXSTD=11,14,17
|
||||
addons:
|
||||
apt:
|
||||
packages:
|
||||
- g++-7
|
||||
sources:
|
||||
- ubuntu-toolchain-r-test
|
||||
- compiler: clang
|
||||
env: |
|
||||
USER_CONFIG="using clang : : clang++ ;"
|
||||
CXXSTD=03,11
|
||||
- compiler: clang
|
||||
env: |
|
||||
USER_CONFIG="using clang : : clang++ -D_HAS_AUTO_PTR_ETC=0 ;"
|
||||
CXXSTD=11
|
||||
|
||||
before_script:
|
||||
- export BOOST_VERSION=1.67.0
|
||||
- export BOOST_FILENAME=boost_1_67_0
|
||||
- export BOOST_ROOT=${HOME}/boost
|
||||
- cd ${TRAVIS_BUILD_DIR}
|
||||
- touch Jamroot.jam
|
||||
- cd $HOME
|
||||
- echo $USER_CONFIG > ~/user-config.jam
|
||||
- cat ~/user-config.jam
|
||||
- |
|
||||
mkdir $HOME/download
|
||||
mkdir $HOME/extract
|
||||
cd $HOME/download
|
||||
if [ "$TRAVIS_EVENT_TYPE" == "cron" ]
|
||||
then
|
||||
if [ "$TRAVIS_BRANCH" == "master" ]
|
||||
then
|
||||
snapshot_branch=master
|
||||
else
|
||||
snapshot_branch=develop
|
||||
fi
|
||||
download_url=$(curl https://api.bintray.com/packages/boostorg/$snapshot_branch/snapshot/files |
|
||||
python -c "import os.path, sys, json; x = json.load(sys.stdin); print '\n'.join(a['path'] for a in x if os.path.splitext(a['path'])[1] == '.bz2')" |
|
||||
head -n 1 |
|
||||
sed "s/^/http:\/\/dl.bintray.com\/boostorg\/$snapshot_branch\//")
|
||||
else
|
||||
download_url=https://sourceforge.net/projects/boost/files/boost/${BOOST_VERSION}/${BOOST_FILENAME}.tar.bz2/download
|
||||
fi
|
||||
echo "Downloading ${download_url}"
|
||||
wget -O boost.tar.bz2 $download_url
|
||||
cd $HOME/extract
|
||||
tar -xjf $HOME/download/boost.tar.bz2
|
||||
mv * ${BOOST_ROOT}
|
||||
- rm -r ${BOOST_ROOT}/boost/functional
|
||||
- cd ${BOOST_ROOT}/tools/build
|
||||
- mkdir ${HOME}/opt
|
||||
- ./bootstrap.sh
|
||||
- ./b2 install --prefix=$HOME/opt
|
||||
|
||||
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
|
45
CMakeLists.txt
Normal file
45
CMakeLists.txt
Normal file
@ -0,0 +1,45 @@
|
||||
# Generated by `boostdep --cmake container_hash`
|
||||
# Copyright 2020, 2021 Peter Dimov
|
||||
# Distributed under the Boost Software License, Version 1.0.
|
||||
# https://www.boost.org/LICENSE_1_0.txt
|
||||
|
||||
if(NOT DEFINED IDF_TARGET)
|
||||
|
||||
cmake_minimum_required(VERSION 3.5...3.20)
|
||||
|
||||
project(boost_container_hash VERSION "${BOOST_SUPERPROJECT_VERSION}" LANGUAGES CXX)
|
||||
|
||||
add_library(boost_container_hash INTERFACE)
|
||||
add_library(Boost::container_hash ALIAS boost_container_hash)
|
||||
|
||||
target_include_directories(boost_container_hash INTERFACE include)
|
||||
|
||||
target_link_libraries(boost_container_hash
|
||||
INTERFACE
|
||||
Boost::config
|
||||
Boost::type_traits
|
||||
)
|
||||
|
||||
if(BUILD_TESTING AND EXISTS "${CMAKE_CURRENT_SOURCE_DIR}/test/CMakeLists.txt")
|
||||
|
||||
add_subdirectory(test)
|
||||
|
||||
endif()
|
||||
|
||||
else()
|
||||
|
||||
FILE(GLOB_RECURSE headers include/*.h include/*.hpp)
|
||||
|
||||
idf_component_register(
|
||||
SRCS
|
||||
${headers}
|
||||
INCLUDE_DIRS
|
||||
include
|
||||
REQUIRES
|
||||
boost_config
|
||||
boost_type_traits
|
||||
)
|
||||
|
||||
endif()
|
||||
|
||||
|
101
benchmark/char_seq.cpp
Normal file
101
benchmark/char_seq.cpp
Normal file
@ -0,0 +1,101 @@
|
||||
// Copyright 2022 Peter Dimov.
|
||||
// Distributed under the Boost Software License, Version 1.0.
|
||||
// https://www.boost.org/LICENSE_1_0.txt
|
||||
|
||||
#define _CRT_SECURE_NO_WARNINGS
|
||||
|
||||
#include <boost/container_hash/hash.hpp>
|
||||
#include <boost/core/detail/splitmix64.hpp>
|
||||
#include <boost/core/type_name.hpp>
|
||||
#include <boost/config.hpp>
|
||||
#include <cstddef>
|
||||
#include <cstdio>
|
||||
#include <cstdint>
|
||||
#include <string>
|
||||
#include <vector>
|
||||
#include <deque>
|
||||
#include <list>
|
||||
#include <chrono>
|
||||
|
||||
// test_hash_speed
|
||||
|
||||
template<class T, class V> void test_hash_speed( int N, V const& v )
|
||||
{
|
||||
std::vector<T> w;
|
||||
|
||||
w.reserve( N );
|
||||
|
||||
for( int i = 0; i < N; ++i )
|
||||
{
|
||||
w.emplace_back( v[i].begin(), v[i].end() );
|
||||
}
|
||||
|
||||
typedef std::chrono::steady_clock clock_type;
|
||||
|
||||
clock_type::time_point t1 = clock_type::now();
|
||||
|
||||
std::size_t q = 0;
|
||||
|
||||
boost::hash<T> const h;
|
||||
|
||||
for( int i = 0; i < N; ++i )
|
||||
{
|
||||
q += h( w[i] );
|
||||
}
|
||||
|
||||
clock_type::time_point t2 = clock_type::now();
|
||||
|
||||
long long ms1 = std::chrono::duration_cast<std::chrono::milliseconds>( t2 - t1 ).count();
|
||||
|
||||
std::string type = boost::core::type_name<T>();
|
||||
|
||||
#if defined( _MSC_VER )
|
||||
|
||||
std::printf( "%25s : q=%20Iu, %lld ms\n", type.c_str(), q, ms1 );
|
||||
|
||||
#else
|
||||
|
||||
std::printf( "%25s : q=%20zu, %lld ms\n", type.c_str(), q, ms1 );
|
||||
|
||||
#endif
|
||||
}
|
||||
|
||||
int main()
|
||||
{
|
||||
int const N = 1048576 * 8;
|
||||
|
||||
std::vector<std::string> v;
|
||||
|
||||
{
|
||||
v.reserve( N );
|
||||
|
||||
boost::detail::splitmix64 rnd;
|
||||
|
||||
for( int i = 0; i < N; ++i )
|
||||
{
|
||||
char buffer[ 64 ];
|
||||
|
||||
unsigned long long k = rnd();
|
||||
|
||||
if( k & 1 )
|
||||
{
|
||||
sprintf( buffer, "prefix_%llu_suffix", k );
|
||||
}
|
||||
else
|
||||
{
|
||||
sprintf( buffer, "{%u}", static_cast<unsigned>( k ) );
|
||||
}
|
||||
|
||||
v.push_back( buffer );
|
||||
}
|
||||
}
|
||||
|
||||
std::puts( "Char sequence hashing test:\n" );
|
||||
|
||||
test_hash_speed< std::string >( N, v );
|
||||
test_hash_speed< std::vector<char> >( N, v );
|
||||
test_hash_speed< std::deque<char> >( N, v );
|
||||
test_hash_speed< std::list<char> >( N, v );
|
||||
|
||||
std::puts( "" );
|
||||
}
|
389
benchmark/unordered.cpp
Normal file
389
benchmark/unordered.cpp
Normal file
@ -0,0 +1,389 @@
|
||||
// Copyright 2022 Peter Dimov.
|
||||
// Distributed under the Boost Software License, Version 1.0.
|
||||
// https://www.boost.org/LICENSE_1_0.txt
|
||||
|
||||
#define _CRT_SECURE_NO_WARNINGS
|
||||
|
||||
#include <boost/container_hash/hash.hpp>
|
||||
#include <boost/unordered_set.hpp>
|
||||
#include <boost/core/detail/splitmix64.hpp>
|
||||
#include <boost/core/type_name.hpp>
|
||||
#include <boost/config.hpp>
|
||||
#include <cstddef>
|
||||
#include <cstdio>
|
||||
#include <cstdint>
|
||||
#include <string>
|
||||
#include <vector>
|
||||
#include <chrono>
|
||||
#include <functional>
|
||||
|
||||
// mul31_hash
|
||||
|
||||
class mul31_hash
|
||||
{
|
||||
public:
|
||||
|
||||
std::size_t operator()( std::string const& st ) const BOOST_NOEXCEPT
|
||||
{
|
||||
char const * p = st.data();
|
||||
std::size_t n = st.size();
|
||||
|
||||
#if SIZE_MAX > UINT32_MAX
|
||||
std::size_t h = 0xCBF29CE484222325ull;
|
||||
#else
|
||||
std::size_t h = 0x811C9DC5u;
|
||||
#endif
|
||||
|
||||
for( std::size_t i = 0; i < n; ++i )
|
||||
{
|
||||
h = h * 31 + static_cast<unsigned char>( p[i] );
|
||||
}
|
||||
|
||||
return h;
|
||||
}
|
||||
};
|
||||
|
||||
// mul31_unrolled_hash
|
||||
|
||||
template<int Bits> struct mul31_unrolled_hash_impl;
|
||||
|
||||
template<> struct mul31_unrolled_hash_impl<32>
|
||||
{
|
||||
std::size_t operator()( std::string const& st ) const BOOST_NOEXCEPT
|
||||
{
|
||||
char const * p = st.data();
|
||||
std::size_t n = st.size();
|
||||
|
||||
std::size_t h = 0x811C9DC5u;
|
||||
|
||||
while( n >= 4 )
|
||||
{
|
||||
h = h * (31u * 31u * 31u * 31u)
|
||||
+ static_cast<unsigned char>( p[0] ) * (31u * 31u * 31u)
|
||||
+ static_cast<unsigned char>( p[1] ) * (31u * 31u)
|
||||
+ static_cast<unsigned char>( p[2] ) * 31u
|
||||
+ static_cast<unsigned char>( p[3] );
|
||||
|
||||
p += 4;
|
||||
n -= 4;
|
||||
}
|
||||
|
||||
while( n > 0 )
|
||||
{
|
||||
h = h * 31u + static_cast<unsigned char>( *p );
|
||||
|
||||
++p;
|
||||
--n;
|
||||
}
|
||||
|
||||
return h;
|
||||
}
|
||||
};
|
||||
|
||||
template<> struct mul31_unrolled_hash_impl<64>
|
||||
{
|
||||
std::size_t operator()( std::string const& st ) const BOOST_NOEXCEPT
|
||||
{
|
||||
char const * p = st.data();
|
||||
std::size_t n = st.size();
|
||||
|
||||
std::size_t h = 0xCBF29CE484222325ull;
|
||||
|
||||
while( n >= 8 )
|
||||
{
|
||||
h = h * (31ull * 31ull * 31ull * 31ull * 31ull * 31ull * 31ull * 31ull)
|
||||
+ static_cast<unsigned char>( p[0] ) * (31ull * 31ull * 31ull * 31ull * 31ull * 31ull * 31ull)
|
||||
+ static_cast<unsigned char>( p[1] ) * (31ull * 31ull * 31ull * 31ull * 31ull * 31ull)
|
||||
+ static_cast<unsigned char>( p[2] ) * (31ull * 31ull * 31ull * 31ull * 31ull)
|
||||
+ static_cast<unsigned char>( p[3] ) * (31ull * 31ull * 31ull * 31ull)
|
||||
+ static_cast<unsigned char>( p[4] ) * (31ull * 31ull * 31ull)
|
||||
+ static_cast<unsigned char>( p[5] ) * (31ull * 31ull)
|
||||
+ static_cast<unsigned char>( p[6] ) * 31ull
|
||||
+ static_cast<unsigned char>( p[7] );
|
||||
|
||||
p += 8;
|
||||
n -= 8;
|
||||
}
|
||||
|
||||
while( n > 0 )
|
||||
{
|
||||
h = h * 31u + static_cast<unsigned char>( *p );
|
||||
|
||||
++p;
|
||||
--n;
|
||||
}
|
||||
|
||||
return h;
|
||||
}
|
||||
};
|
||||
|
||||
struct mul31_unrolled_hash: mul31_unrolled_hash_impl< std::numeric_limits<std::size_t>::digits > {};
|
||||
|
||||
// fnv1a_hash
|
||||
|
||||
template<int Bits> struct fnv1a_hash_impl;
|
||||
|
||||
template<> struct fnv1a_hash_impl<32>
|
||||
{
|
||||
std::size_t operator()( std::string const& s ) const
|
||||
{
|
||||
std::size_t h = 0x811C9DC5u;
|
||||
|
||||
char const * first = s.data();
|
||||
char const * last = first + s.size();
|
||||
|
||||
for( ; first != last; ++first )
|
||||
{
|
||||
h ^= static_cast<unsigned char>( *first );
|
||||
h *= 0x01000193ul;
|
||||
}
|
||||
|
||||
return h;
|
||||
}
|
||||
};
|
||||
|
||||
template<> struct fnv1a_hash_impl<64>
|
||||
{
|
||||
std::size_t operator()( std::string const& s ) const
|
||||
{
|
||||
std::size_t h = 0xCBF29CE484222325ull;
|
||||
|
||||
char const * first = s.data();
|
||||
char const * last = first + s.size();
|
||||
|
||||
for( ; first != last; ++first )
|
||||
{
|
||||
h ^= static_cast<unsigned char>( *first );
|
||||
h *= 0x00000100000001B3ull;
|
||||
}
|
||||
|
||||
return h;
|
||||
}
|
||||
};
|
||||
|
||||
struct fnv1a_hash: fnv1a_hash_impl< std::numeric_limits<std::size_t>::digits > {};
|
||||
|
||||
// old_boost_hash
|
||||
|
||||
class old_boost_hash
|
||||
{
|
||||
public:
|
||||
|
||||
std::size_t operator()( std::string const& st ) const BOOST_NOEXCEPT
|
||||
{
|
||||
char const * p = st.data();
|
||||
std::size_t n = st.size();
|
||||
|
||||
std::size_t h = 0;
|
||||
|
||||
for( std::size_t i = 0; i < n; ++i )
|
||||
{
|
||||
h ^= static_cast<unsigned char>( p[i] ) + 0x9e3779b9 + ( h << 6 ) + ( h >> 2 );
|
||||
}
|
||||
|
||||
return h;
|
||||
}
|
||||
};
|
||||
|
||||
// test_hash_speed
|
||||
|
||||
template<class H, class V> void test_hash_speed( int N, V const& v )
|
||||
{
|
||||
typedef std::chrono::steady_clock clock_type;
|
||||
|
||||
clock_type::time_point t1 = clock_type::now();
|
||||
|
||||
std::size_t q = 0;
|
||||
|
||||
H const h;
|
||||
|
||||
for( int i = 0; i < N; ++i )
|
||||
{
|
||||
q += h( v[i] );
|
||||
}
|
||||
|
||||
clock_type::time_point t2 = clock_type::now();
|
||||
|
||||
long long ms1 = std::chrono::duration_cast<std::chrono::milliseconds>( t2 - t1 ).count();
|
||||
|
||||
std::string hash = boost::core::type_name<H>();
|
||||
|
||||
#if defined( _MSC_VER )
|
||||
|
||||
std::printf( "%25s : q=%20Iu, %lld ms\n", hash.c_str(), q, ms1 );
|
||||
|
||||
#else
|
||||
|
||||
std::printf( "%25s : q=%20zu, %lld ms\n", hash.c_str(), q, ms1 );
|
||||
|
||||
#endif
|
||||
}
|
||||
|
||||
// test_hash_collision
|
||||
|
||||
template<class H, class V> void test_hash_collision( int N, V const& v, std::size_t n )
|
||||
{
|
||||
boost::unordered_set<std::size_t> s;
|
||||
H const h;
|
||||
|
||||
for( int i = 0; i < N; ++i )
|
||||
{
|
||||
s.insert( h( v[i] ) );
|
||||
}
|
||||
|
||||
std::string hash = boost::core::type_name<H>();
|
||||
|
||||
#if defined( _MSC_VER )
|
||||
|
||||
std::printf( "%25s : c=%Iu\n", hash.c_str(), n - s.size() );
|
||||
|
||||
#else
|
||||
|
||||
std::printf( "%25s : c=%zu\n", hash.c_str(), n - s.size() );
|
||||
|
||||
#endif
|
||||
}
|
||||
|
||||
// test_container_speed
|
||||
|
||||
template<class V, class S> void test4( int N, V const& v, char const * hash, S s )
|
||||
{
|
||||
typedef std::chrono::steady_clock clock_type;
|
||||
|
||||
clock_type::time_point t1 = clock_type::now();
|
||||
|
||||
for( int i = 0; i < N; ++i )
|
||||
{
|
||||
s.insert( v[ i * 16 ] );
|
||||
}
|
||||
|
||||
clock_type::time_point t2 = clock_type::now();
|
||||
|
||||
std::size_t q = 0;
|
||||
|
||||
for( int i = 0; i < 16 * N; ++i )
|
||||
{
|
||||
q += s.count( v[ i ] );
|
||||
}
|
||||
|
||||
clock_type::time_point t3 = clock_type::now();
|
||||
|
||||
long long ms1 = std::chrono::duration_cast<std::chrono::milliseconds>( t2 - t1 ).count();
|
||||
long long ms2 = std::chrono::duration_cast<std::chrono::milliseconds>( t3 - t2 ).count();
|
||||
|
||||
std::size_t n = s.bucket_count();
|
||||
std::size_t m = 0;
|
||||
std::size_t c = 0;
|
||||
|
||||
for( std::size_t i = 0; i < n; ++i )
|
||||
{
|
||||
std::size_t k = s.bucket_size( i );
|
||||
|
||||
if( k > 1 )
|
||||
{
|
||||
c += k - 1;
|
||||
}
|
||||
|
||||
if( k > m )
|
||||
{
|
||||
m = k;
|
||||
}
|
||||
}
|
||||
|
||||
#if defined( _MSC_VER )
|
||||
|
||||
std::printf( "%25s : n=%Iu, m=%Iu, c=%Iu, q=%Iu, %lld + %lld ms\n", hash, n, m, c, q, ms1, ms2 );
|
||||
|
||||
#else
|
||||
|
||||
std::printf( "%25s : n=%zu, m=%zu, c=%zu, q=%zu, %lld + %lld ms\n", hash, n, m, c, q, ms1, ms2 );
|
||||
|
||||
#endif
|
||||
}
|
||||
|
||||
template<class K, class H, class V> void test_container_speed( int N, V const& v )
|
||||
{
|
||||
boost::unordered_set<K, H> s( 0 );
|
||||
test4( N, v, boost::core::type_name<H>().c_str(), s );
|
||||
}
|
||||
|
||||
int main()
|
||||
{
|
||||
int const N = 1048576 / 2; // 1048576 is too much for 32 bit
|
||||
|
||||
std::vector<std::string> v;
|
||||
|
||||
{
|
||||
v.reserve( N * 16 );
|
||||
|
||||
boost::detail::splitmix64 rnd;
|
||||
|
||||
for( int i = 0; i < 16 * N; ++i )
|
||||
{
|
||||
char buffer[ 64 ];
|
||||
|
||||
unsigned long long k = rnd();
|
||||
|
||||
if( k & 1 )
|
||||
{
|
||||
sprintf( buffer, "prefix_%llu_suffix", k );
|
||||
}
|
||||
else
|
||||
{
|
||||
sprintf( buffer, "{%u}", static_cast<unsigned>( k ) );
|
||||
}
|
||||
|
||||
v.push_back( buffer );
|
||||
}
|
||||
}
|
||||
|
||||
std::puts( "Hash speed test:\n" );
|
||||
|
||||
test_hash_speed<mul31_hash>( N * 16, v );
|
||||
test_hash_speed<mul31_unrolled_hash>( N * 16, v );
|
||||
test_hash_speed<fnv1a_hash>( N * 16, v );
|
||||
test_hash_speed<old_boost_hash>( N * 16, v );
|
||||
test_hash_speed<boost::hash<std::string> >( N * 16, v );
|
||||
test_hash_speed<std::hash<std::string> >( N * 16, v );
|
||||
|
||||
std::puts( "" );
|
||||
|
||||
std::puts( "Hash collision test:\n" );
|
||||
|
||||
{
|
||||
std::size_t n = 0;
|
||||
|
||||
{
|
||||
boost::unordered_set<std::string> s;
|
||||
|
||||
for( int i = 0; i < N * 16; ++i )
|
||||
{
|
||||
s.insert( v[i] );
|
||||
}
|
||||
|
||||
n = s.size();
|
||||
}
|
||||
|
||||
test_hash_collision<mul31_hash>( N * 16, v, n );
|
||||
test_hash_collision<mul31_unrolled_hash>( N * 16, v, n );
|
||||
test_hash_collision<fnv1a_hash>( N * 16, v, n );
|
||||
test_hash_collision<old_boost_hash>( N * 16, v, n );
|
||||
test_hash_collision<boost::hash<std::string> >( N * 16, v, n );
|
||||
test_hash_collision<std::hash<std::string> >( N * 16, v, n );
|
||||
}
|
||||
|
||||
std::puts( "" );
|
||||
|
||||
typedef std::string K;
|
||||
|
||||
std::puts( "Container speed test:\n" );
|
||||
|
||||
test_container_speed<K, mul31_hash>( N, v );
|
||||
test_container_speed<K, mul31_unrolled_hash>( N, v );
|
||||
test_container_speed<K, fnv1a_hash>( N, v );
|
||||
test_container_speed<K, old_boost_hash>( N, v );
|
||||
test_container_speed<K, boost::hash<std::string> >( N, v );
|
||||
test_container_speed<K, std::hash<std::string> >( N, v );
|
||||
|
||||
std::puts( "" );
|
||||
}
|
2
doc/.gitignore
vendored
Normal file
2
doc/.gitignore
vendored
Normal file
@ -0,0 +1,2 @@
|
||||
/html/
|
||||
/pdf/
|
22
doc/Jamfile.v2
Normal file
22
doc/Jamfile.v2
Normal file
@ -0,0 +1,22 @@
|
||||
|
||||
# Copyright 2005-2008 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)
|
||||
|
||||
import asciidoctor ;
|
||||
|
||||
html hash.html : hash.adoc ;
|
||||
|
||||
install html_ : hash.html : <location>html ;
|
||||
|
||||
pdf hash.pdf : hash.adoc ;
|
||||
explicit hash.pdf ;
|
||||
|
||||
install pdf_ : hash.pdf : <location>pdf ;
|
||||
explicit pdf_ ;
|
||||
|
||||
###############################################################################
|
||||
alias boostdoc ;
|
||||
explicit boostdoc ;
|
||||
alias boostrelease : html_ ;
|
||||
explicit boostrelease ;
|
24
doc/hash.adoc
Normal file
24
doc/hash.adoc
Normal file
@ -0,0 +1,24 @@
|
||||
= Boost.ContainerHash
|
||||
:toc: left
|
||||
:toclevels: 2
|
||||
:idprefix:
|
||||
:docinfo: private-footer
|
||||
:source-highlighter: rouge
|
||||
:nofooter:
|
||||
:sectlinks:
|
||||
:source-language: c++
|
||||
|
||||
:leveloffset: +1
|
||||
|
||||
include::hash/intro.adoc[]
|
||||
include::hash/tutorial.adoc[]
|
||||
include::hash/custom.adoc[]
|
||||
include::hash/combine.adoc[]
|
||||
include::hash/portability.adoc[]
|
||||
include::hash/disable.adoc[]
|
||||
include::hash/changes.adoc[]
|
||||
include::hash/rationale.adoc[]
|
||||
include::hash/ref.adoc[]
|
||||
include::hash/links.adoc[]
|
||||
include::hash/thanks.adoc[]
|
||||
include::hash/copyright.adoc[]
|
132
doc/hash/changes.adoc
Normal file
132
doc/hash/changes.adoc
Normal file
@ -0,0 +1,132 @@
|
||||
[#changes]
|
||||
= Change Log
|
||||
|
||||
:cpp: C++
|
||||
:int128: __int128
|
||||
|
||||
:idprefix: changes_
|
||||
|
||||
== Boost 1.67.0
|
||||
* Moved library into its own module, `container_hash`.
|
||||
* Moved headers for new module name, now at: `<boost/container_hash/hash.hpp>`, `<boost/container_hash/hash_fwd.hpp>`, `<boost/container_hash/extensions.hpp>`.
|
||||
* Added forwarding headers to support the old headers locations.
|
||||
* Support `std::string_view`, `std::error_code`, `std::error_condition`, `std::optional`, `std::variant`, `std::monostate` where available.
|
||||
* Update include paths from other Boost libraries.
|
||||
* Manually write out tuple overloads, rather than using the preprocessor to generate them. Should improve usability, due to better error messages, and easier debugging.
|
||||
* Fix tutorial example (https://svn.boost.org/trac/boost/ticket/11017[#11017]).
|
||||
* Quick fix for hashing `vector<bool>` when using lib{cpp}. Will try to introduce a more general fix in the next release.
|
||||
|
||||
== Boost 1.66.0
|
||||
* Avoid float comparison warning when using Clang - this workaround was already in place for GCC, and was used when Clang pretends to be GCC, but the warning was appearing when running Clang in other contexts.
|
||||
|
||||
== Boost 1.65.0
|
||||
* Support for `char16_t`, `char32_t`, `u16string`, `u32string`
|
||||
|
||||
== Boost 1.64.0
|
||||
* Fix for recent versions of Visual {cpp} which have removed `std::unary_function` and `std::binary_function` (https://svn.boost.org/trac/boost/ticket/12353[#12353]).
|
||||
|
||||
== Boost 1.63.0
|
||||
* Fixed some warnings.
|
||||
* Only define hash for `std::wstring` when we know we have a `wchar_t`. Otherwise there's a compile error as there's no overload for hashing the characters in wide strings (https://svn.boost.org/trac/boost/ticket/8552[#8552]).
|
||||
|
||||
== Boost 1.58.0
|
||||
* Fixed strict aliasing violation (https://github.com/boostorg/container_hash/issues/3[GitHub #3]).
|
||||
|
||||
== Boost 1.56.0
|
||||
* Removed some Visual {cpp} 6 workarounds.
|
||||
* Ongoing work on improving `hash_combine`. This changes the combine function which was previously defined in the reference documentation.
|
||||
|
||||
== Boost 1.55.0
|
||||
* Simplify a SFINAE check so that it will hopefully work on Sun 5.9 (https://svn.boost.org/trac10/ticket/8822[#8822]).
|
||||
* Suppress Visual {cpp} infinite loop warning (https://svn.boost.org/trac10/ticket/8568[#8568]).
|
||||
|
||||
== Boost 1.54.0
|
||||
* https://svn.boost.org/trac/boost/ticket/7957[Ticket 7957]: Fixed a typo.
|
||||
|
||||
== Boost 1.53.0
|
||||
* Add support for `boost::int128_type` and `boost::uint128_type` where available - currently only `{int128}` and `unsigned {int128}` on some versions of gcc.
|
||||
* On platforms that are known to have the standard floating point functions, don't use automatic detection - which can break if there are ambiguous overloads.
|
||||
* Fix undefined behaviour when using the binary `float` hash (Thomas Heller).
|
||||
|
||||
== Boost 1.52.0
|
||||
* Restore `enum` support, which was accidentally removed in the last version.
|
||||
* New floating point hasher - will hash the binary representation on more platforms, which should be faster.
|
||||
|
||||
== Boost 1.51.0
|
||||
* Support the standard smart pointers.
|
||||
* `hash_value` now implemented using SFINAE to avoid implicit casts to built in types when calling it.
|
||||
* Updated to use the new config macros.
|
||||
|
||||
== Boost 1.50.0
|
||||
* https://svn.boost.org/trac/boost/ticket/6771[Ticket 6771]: Avoid gcc's `-Wfloat-equal` warning.
|
||||
* https://svn.boost.org/trac/boost/ticket/6806[Ticket 6806]: Support `std::array` and `std::tuple` when available.
|
||||
* Add deprecation warning to the long deprecated `boost/container_hash/detail/container_fwd.hpp`.
|
||||
|
||||
== Boost 1.46.0
|
||||
* Avoid warning due with gcc's `-Wconversion` flag.
|
||||
|
||||
== Boost 1.44.0
|
||||
* Add option to prevent implicit conversions when calling `hash_value` by defining `BOOST_HASH_NO_IMPLICIT_CASTS`. When using `boost::hash` for a type that does not have `hash_value` declared but does have an implicit conversion to a type that does, it would use that implicit conversion to hash it. Which can sometimes go very wrong, e.g. using a conversion to `bool` and only hashing to 2 possible values. Since fixing this is a breaking change and was only approached quite late in the release cycle with little discussion it's opt-in for now. This, or something like it, will become the default in a future version.
|
||||
|
||||
== Boost 1.43.0
|
||||
* https://svn.boost.org/trac/boost/ticket/3866[Ticket 3866]: Don't foward declare containers when using gcc's parallel library, allow user to stop forward declaration by defining the `BOOST_DETAIL_NO_CONTAINER_FWD` macro.
|
||||
* https://svn.boost.org/trac/boost/ticket/4038[Ticket 4038]: Avoid hashing `0.5` and `0` to the same number.
|
||||
* Stop using deprecated `BOOST_HAS_*` macros.
|
||||
|
||||
== Boost 1.42.0
|
||||
* Reduce the number of warnings for Visual {cpp} warning level 4.
|
||||
* Some code formatting changes to fit lines into 80 characters.
|
||||
* Rename an internal namespace.
|
||||
|
||||
== Boost 1.40.0
|
||||
* Automatically configure the `float` functions using template metaprogramming instead of trying to configure every possibility manually.
|
||||
* Workaround for when STLport doesn't support long double.
|
||||
|
||||
== Boost 1.39.0
|
||||
* Move the `hash_fwd.hpp` implementation into the hash subdirectory, leaving a forwarding header in the old location. You should still use the old location, the new location is mainly for implementation and possible modularization.
|
||||
* https://svn.boost.org/trac/boost/ticket/2412[Ticket 2412]: Removed deprecated headers.
|
||||
* https://svn.boost.org/trac/boost/ticket/2957[Ticket 2957]: Fix configuration for vxworks.
|
||||
|
||||
== Boost 1.38.0
|
||||
* Changed the warnings in the deprecated headers from 1.34.0 to errors. These will be removed in a future version of Boost.
|
||||
* Moved detail headers out of `boost/container_hash/detail`, since they are part of `functional/hash`, not `container_hash`. `boost/container_hash/detail/container_fwd.hpp` has been moved to `boost/detail/container_fwd.hpp` as it's used outside of this library, the others have been moved to `boost/functional/hash/detail`.
|
||||
|
||||
== Boost 1.37.0
|
||||
* http://svn.boost.org/trac/boost/ticket/2264[Ticket 2264]: In Visual {cpp}, always use C99 float functions for long double and float as the {cpp} overloads aren't always availables.
|
||||
|
||||
== Boost 1.36.0
|
||||
* Stop using OpenBSD's dodgy `std::numeric_limits`.
|
||||
* Using the boost typedefs for `long long` and `unsigned long long`.
|
||||
* Move the extensions into their own header.
|
||||
|
||||
== Boost 1.35.0
|
||||
* Support for `long long`, `std::complex`.
|
||||
* Improved algorithm for hashing floating point numbers:
|
||||
** Improved portablity, as described by Daniel Krügler in http://lists.boost.org/boost-users/2005/08/13418.php[a post to the boost users list].
|
||||
** Fits more information into each combine loop, which can reduce the the number of times combine is called and hopefully give a better quality hash function.
|
||||
** Improved the algorithm for hashing floating point numbers.
|
||||
** On Cygwin use a binary hash function for floating point numbers, as Cygwin doesn't have decent floating point functions for `long double`.
|
||||
** Never uses `fpclass` which doesn't support `long double`.
|
||||
** http://svn.boost.org/trac/boost/ticket/1064[Ticket 1064]: Removed unnecessary use of errno.
|
||||
* Explicitly overload for more built in types.
|
||||
* Minor improvements to the documentation.
|
||||
* A few bug and warning fixes:
|
||||
** http://svn.boost.org/trac/boost/ticket/1509[Ticket 1509]: Suppress another Visual {cpp} warning.
|
||||
** Some workarounds for the Sun compilers.
|
||||
|
||||
== Boost 1.34.1
|
||||
* https://svn.boost.org/trac10/ticket/952[Ticket 952]: Suppress incorrect 64-bit warning on Visual {cpp}.
|
||||
|
||||
== Boost 1.34.0
|
||||
* Use declarations for standard classes, so that the library doesn't need to include all of their headers
|
||||
* Deprecated the `<boost/functional/hash/*.hpp>` headers. Now a single header, `<boost/functional/hash.hpp>` is used.
|
||||
* Add support for the `BOOST_HASH_NO_EXTENSIONS` macro, which disables the extensions to TR1.
|
||||
* Minor improvements to the hash functions for floating point numbers.
|
||||
* Update the portable example to hopefully be more generally portable.
|
||||
|
||||
== Boost 1.33.1
|
||||
* Fixed the points example, as pointed out by 沈慧峰.
|
||||
|
||||
== Boost 1.33.0
|
||||
* Initial Release
|
||||
|
80
doc/hash/combine.adoc
Normal file
80
doc/hash/combine.adoc
Normal file
@ -0,0 +1,80 @@
|
||||
[#combine]
|
||||
= Combining hash values
|
||||
|
||||
:idprefix: combine_
|
||||
|
||||
Say you have a point class, representing a two dimensional location:
|
||||
|
||||
[source]
|
||||
----
|
||||
class point
|
||||
{
|
||||
int x;
|
||||
int y;
|
||||
public:
|
||||
point() : x(0), y(0) {}
|
||||
point(int x, int y) : x(x), y(y) {}
|
||||
|
||||
bool operator==(point const& other) const
|
||||
{
|
||||
return x == other.x && y == other.y;
|
||||
}
|
||||
};
|
||||
----
|
||||
|
||||
and you wish to use it as the key for an unordered_map. You need to customise the hash for this structure. To do this we need to combine the hash values for x and y. The function `boost::hash_combine` is supplied for this purpose:
|
||||
|
||||
[source]
|
||||
----
|
||||
class point
|
||||
{
|
||||
...
|
||||
|
||||
friend std::size_t hash_value(point const& p)
|
||||
{
|
||||
std::size_t seed = 0;
|
||||
boost::hash_combine(seed, p.x);
|
||||
boost::hash_combine(seed, p.y);
|
||||
|
||||
return seed;
|
||||
}
|
||||
|
||||
...
|
||||
};
|
||||
----
|
||||
|
||||
Calls to `hash_combine` incrementally build the hash from the different members of `point`, it can be repeatedly called for any number of elements. It calls `hash_value` on the supplied element, and combines it with the seed.
|
||||
|
||||
Full code for this example is at link:../../examples/point.cpp[/libs/container_hash/examples/point.cpp].
|
||||
|
||||
[NOTE]
|
||||
====
|
||||
When using `boost::hash_combine` the order of the calls matters.
|
||||
[source]
|
||||
----
|
||||
std::size_t seed = 0;
|
||||
boost::hash_combine(seed, 1);
|
||||
boost::hash_combine(seed, 2);
|
||||
----
|
||||
results in a different seed to:
|
||||
|
||||
[source]
|
||||
----
|
||||
std::size_t seed = 0;
|
||||
boost::hash_combine(seed, 2);
|
||||
boost::hash_combine(seed, 1);
|
||||
----
|
||||
|
||||
If you are calculating a hash value for data where the order of the data doesn't matter in comparisons (e.g. a set) you will have to ensure that the data is always supplied in the same order.
|
||||
|
||||
====
|
||||
|
||||
To calculate the hash of an iterator range you can use `boost::hash_range`:
|
||||
|
||||
[source]
|
||||
----
|
||||
std::vector<std::string> some_strings;
|
||||
std::size_t hash = boost::hash_range(some_strings.begin(), some_strings.end());
|
||||
----
|
||||
|
||||
Note that when writing template classes, you might not want to include the main hash header as it's quite an expensive include that brings in a lot of other headers, so instead you can include the `<boost/container_hash/hash_fwd.hpp>` header which forward declares `boost::hash`, `boost::hash_range` and `boost::hash_combine`. You'll need to include the main header before instantiating `boost::hash`. When using a container that uses `boost::hash` it should do that for you, so your type will work fine with the boost hash containers. There's an example of this in link:../../examples/template.hpp[template.hpp] and link:../../examples/template.cpp[template.cpp].
|
10
doc/hash/copyright.adoc
Normal file
10
doc/hash/copyright.adoc
Normal file
@ -0,0 +1,10 @@
|
||||
[#copyright]
|
||||
= Copyright and License
|
||||
|
||||
:idprefix: copyright_
|
||||
|
||||
*Daniel James*
|
||||
|
||||
Copyright (C) 2005-2008 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)
|
68
doc/hash/custom.adoc
Normal file
68
doc/hash/custom.adoc
Normal file
@ -0,0 +1,68 @@
|
||||
[#custom]
|
||||
= Extending boost::hash for a custom data type
|
||||
|
||||
:idprefix: custom_
|
||||
|
||||
`boost::hash` is implemented by calling the function `hash_value`. The namespace isn't specified so that it can detect overloads via argument dependant lookup. So if there is a free function `hash_value` in the same namespace as a custom type, it will get called.
|
||||
|
||||
If you have a structure `library::book`, where each book is uniquely defined by its member `id`:
|
||||
|
||||
[source]
|
||||
----
|
||||
namespace library
|
||||
{
|
||||
struct book
|
||||
{
|
||||
int id;
|
||||
std::string author;
|
||||
std::string title;
|
||||
|
||||
// ....
|
||||
};
|
||||
|
||||
bool operator==(book const& a, book const& b)
|
||||
{
|
||||
return a.id == b.id;
|
||||
}
|
||||
}
|
||||
----
|
||||
|
||||
Then all you would need to do is write the function `library::hash_value`:
|
||||
|
||||
[source]
|
||||
----
|
||||
namespace library
|
||||
{
|
||||
std::size_t hash_value(book const& b)
|
||||
{
|
||||
boost::hash<int> hasher;
|
||||
return hasher(b.id);
|
||||
}
|
||||
}
|
||||
----
|
||||
|
||||
And you can now use `boost::hash` with book:
|
||||
|
||||
[source]
|
||||
----
|
||||
library::book knife(3458, "Zane Grey", "The Hash Knife Outfit");
|
||||
library::book dandelion(1354, "Paul J. Shanley",
|
||||
"Hash & Dandelion Greens");
|
||||
|
||||
boost::hash<library::book> book_hasher;
|
||||
std::size_t knife_hash_value = book_hasher(knife);
|
||||
|
||||
// If std::unordered_set is available:
|
||||
std::unordered_set<library::book, boost::hash<library::book> > books;
|
||||
books.insert(knife);
|
||||
books.insert(library::book(2443, "Lindgren, Torgny", "Hash"));
|
||||
books.insert(library::book(1953, "Snyder, Bernadette M.",
|
||||
"Heavenly Hash: A Tasty Mix of a Mother's Meditations"));
|
||||
|
||||
assert(books.find(knife) != books.end());
|
||||
assert(books.find(dandelion) == books.end());
|
||||
----
|
||||
|
||||
The full example can be found in: link:../../examples/books.hpp[/libs/container_hash/examples/books.hpp] and link:../../examples/books.cpp[/libs/container_hash/examples/books.cpp].
|
||||
|
||||
TIP: When writing a hash function, first look at how the equality function works. Objects that are equal must generate the same hash value. When objects are not equal they should generate different hash values. In this object equality was based just on the id so the hash function only hashes the id. If it was based on the object's name and author then the hash function should take them into account (how to do this is discussed in the next section).
|
12
doc/hash/disable.adoc
Normal file
12
doc/hash/disable.adoc
Normal file
@ -0,0 +1,12 @@
|
||||
[#disable]
|
||||
= Disabling The Extensions
|
||||
|
||||
:idprefix: disable_
|
||||
|
||||
While ``boost::hash``'s extensions are generally useful, you might want to turn them of in order to check that your code will work with other implementations of TR1. To do this define the macro `BOOST_HASH_NO_EXTENSIONS`. When this macro is defined, only the specialisations detailed in TR1 will be declared. But, if you later undefine the macro and include `<boost/container_hash/hash.hpp>` then the non-specialised form will be defined - activating the extensions.
|
||||
|
||||
It is strongly recommended that you never undefine the macro - and only define it so that it applies to the complete translation unit, either by defining it at the beginning of the main source file or, preferably, by using a compiler switch or preference. And you really should never define it in header files.
|
||||
|
||||
If you are writing a library which has code in the header which requires the extensions, then the best action is to tell users not to define the macro. Their code won't _require_ the macro.
|
||||
|
||||
Translation units that are compiled with the macro defined will link with units that were compiled without it. This feature has been designed to avoid ODR violations.
|
22
doc/hash/intro.adoc
Normal file
22
doc/hash/intro.adoc
Normal file
@ -0,0 +1,22 @@
|
||||
[#intro]
|
||||
= Introduction
|
||||
|
||||
:idprefix: intro_
|
||||
|
||||
`boost::hash` is an implementation of the https://en.wikipedia.org/wiki/Hash_function[hash function] object specified by the http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2005/n1836.pdf[Draft Technical Report on C++ Library Extensions] (TR1). It is the default hash function for link:../../../unordered/index.html[Boost.Unordered], link:../../../intrusive/index.html[Boost.Intrusive]'s unordered associative containers, and link:../../../multi_index/index.html[Boost.MultiIndex]'s hash indicies and link:../../../bimap/index.html[Boost.Bimap]'s `unordered_set_of`.
|
||||
|
||||
As it is compliant with http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2005/n1836.pdf[TR1], it will work with:
|
||||
|
||||
* integers
|
||||
* floats
|
||||
* pointers
|
||||
* strings
|
||||
|
||||
It also implements the extension proposed by Peter Dimov in issue 6.18 of the http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2005/n1837.pdf[Library Extension Technical Report Issues List] (page 63), this adds support for:
|
||||
|
||||
* arrays
|
||||
* `std::pair`
|
||||
* the standard containers.
|
||||
* extending `boost::hash` for custom types.
|
||||
|
||||
NOTE: This hash function is designed to be used in containers based on the STL and is not suitable as a general purpose hash function. For more details see the <<rationale,rationale>>.
|
12
doc/hash/links.adoc
Normal file
12
doc/hash/links.adoc
Normal file
@ -0,0 +1,12 @@
|
||||
[#links]
|
||||
= Links
|
||||
|
||||
:idprefix: links_
|
||||
|
||||
*A Proposal to Add Hash Tables to the Standard Library* http://www.open-std.org/JTC1/SC22/WG21/docs/papers/2003/n1456.html The hash table proposal explains much of the design. The hash function object is discussed in Section D.
|
||||
|
||||
*The C++ Standard Library Technical Report.* http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2005/n1836.pdf Contains the hash function specification in section 6.3.2.
|
||||
|
||||
*Library Extension Technical Report Issues List.* http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2005/n1837.pdf The library implements the extension described in Issue 6.18, pages 63-67.
|
||||
|
||||
*Methods for Identifying Versioned and Plagiarised Documents* Timothy C. Hoad, Justin Zobel http://www.cs.rmit.edu.au/~jz/fulltext/jasist-tch.pdf Contains the hash function that `boost::hash_combine` is based on.
|
82
doc/hash/portability.adoc
Normal file
82
doc/hash/portability.adoc
Normal file
@ -0,0 +1,82 @@
|
||||
[#portability]
|
||||
= Portability
|
||||
|
||||
:idprefix: portability_
|
||||
|
||||
`boost::hash` is written to be as portable as possible, but unfortunately, several older compilers don't support argument dependent lookup (ADL) - the mechanism used for customisation. On those compilers custom overloads for `hash_value` needs to be declared in the `boost` namespace.
|
||||
|
||||
On a strictly standards compliant compiler, an overload defined in the `boost` namespace won't be found when `boost::hash` is instantiated, so for these compilers the overload should only be declared in the same namespace as the class.
|
||||
|
||||
Let's say we have a simple custom type:
|
||||
|
||||
[source]
|
||||
----
|
||||
namespace foo
|
||||
{
|
||||
template <class T>
|
||||
class custom_type
|
||||
{
|
||||
T value;
|
||||
public:
|
||||
custom_type(T x) : value(x) {}
|
||||
|
||||
friend std::size_t hash_value(custom_type x)
|
||||
{
|
||||
boost::hash<int> hasher;
|
||||
return hasher(x.value);
|
||||
}
|
||||
};
|
||||
}
|
||||
----
|
||||
|
||||
On a compliant compiler, when `hash_value` is called for this type, it will look at the namespace inside the type and find `hash_value` but on a compiler which doesn't support ADL `hash_value` won't be found. To make things worse, some compilers which do support ADL won't find a friend class defined inside the class.
|
||||
|
||||
So first move the member function out of the class:
|
||||
|
||||
[source]
|
||||
----
|
||||
namespace foo
|
||||
{
|
||||
template <class T>
|
||||
class custom_type
|
||||
{
|
||||
T value;
|
||||
public:
|
||||
custom_type(T x) : value(x) {}
|
||||
|
||||
std::size_t hash(custom_type x)
|
||||
{
|
||||
boost::hash<T> hasher;
|
||||
return hasher(value);
|
||||
}
|
||||
};
|
||||
|
||||
template <class T>
|
||||
inline std::size_t hash_value(custom_type<T> x)
|
||||
{
|
||||
return x.hash();
|
||||
}
|
||||
}
|
||||
----
|
||||
|
||||
Unfortunately, I couldn't declare `hash_value` as a friend, as some compilers don't support template friends, so instead I declared a member function to calculate the hash, and called it from `hash_value`.
|
||||
|
||||
For compilers which don't support ADL, `hash_value` needs to be defined in the `boost` namespace:
|
||||
|
||||
[source]
|
||||
----
|
||||
#ifdef BOOST_NO_ARGUMENT_DEPENDENT_LOOKUP
|
||||
namespace boost
|
||||
#else
|
||||
namespace foo
|
||||
#endif
|
||||
{
|
||||
template <class T>
|
||||
std::size_t hash_value(foo::custom_type<T> x)
|
||||
{
|
||||
return x.hash();
|
||||
}
|
||||
}
|
||||
----
|
||||
|
||||
Full code for this example is at link:../../examples/portable.cpp[/libs/container_hash/examples/portable.cpp].
|
16
doc/hash/rationale.adoc
Normal file
16
doc/hash/rationale.adoc
Normal file
@ -0,0 +1,16 @@
|
||||
[#rationale]
|
||||
= Rationale
|
||||
|
||||
:idprefix: rationale_
|
||||
|
||||
The rationale can be found in the original designfootnote:[issue 6.18 of the http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2005/n1837.pdf[Library Extension Technical Report Issues List] (page 63)].
|
||||
|
||||
== Quality of the hash function
|
||||
|
||||
Many hash functions strive to have little correlation between the input and output values. They attempt to uniformally distribute the output values for very similar inputs. This hash function makes no such attempt. In fact, for integers, the result of the hash function is often just the input value. So similar but different input values will often result in similar but different output values. This means that it is not appropriate as a general hash function. For example, a hash table may discard bits from the hash function resulting in likely collisions, or might have poor collision resolution when hash values are clustered together. In such cases this hash function will preform poorly.
|
||||
|
||||
But the standard has no such requirement for the hash function, it just requires that the hashes of two different values are unlikely to collide. Containers or algorithms designed to work with the standard hash function will have to be implemented to work well when the hash function's output is correlated to its input. Since they are paying that cost a higher quality hash function would be wasteful.
|
||||
|
||||
For other use cases, if you do need a higher quality hash function, then neither the standard hash function or `boost::hash` are appropriate. There are several options available. One is to use a second hash on the output of this hash function, such as http://web.archive.org/web/20121102023700/http://www.concentric.net/~Ttwang/tech/inthash.htm[Thomas Wang's hash function]. This this may not work as well as a hash algorithm tailored for the input.
|
||||
|
||||
For strings there are several fast, high quality hash functions available (for example http://code.google.com/p/smhasher/[MurmurHash3] and http://code.google.com/p/cityhash/[Google's CityHash]), although they tend to be more machine specific. These may also be appropriate for hashing a binary representation of your data - providing that all equal values have an equal representation, which is not always the case (e.g. for floating point values).
|
386
doc/hash/ref.adoc
Normal file
386
doc/hash/ref.adoc
Normal file
@ -0,0 +1,386 @@
|
||||
[#ref]
|
||||
= Reference
|
||||
|
||||
:idprefix: ref_
|
||||
|
||||
For the full specification, see section 6.3 of the http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2005/n1836.pdf[C++ Standard Library Technical Report] and issue 6.18 of the http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2005/n1837.pdf[Library Extension Technical Report Issues List] (page 63).
|
||||
|
||||
== Header <boost/container_hash/hash.hpp>
|
||||
|
||||
Defines `boost::hash`, and helper functions.
|
||||
|
||||
[source]
|
||||
----
|
||||
namespace boost {
|
||||
template<typename T> struct hash;
|
||||
|
||||
template<> struct hash<bool>;
|
||||
template<> struct hash<char>;
|
||||
template<> struct hash<signed char>;
|
||||
template<> struct hash<unsigned char>;
|
||||
template<> struct hash<wchar_t>;
|
||||
template<> struct hash<char16_t>;
|
||||
template<> struct hash<char32_t>;
|
||||
template<> struct hash<short>;
|
||||
template<> struct hash<unsigned short>;
|
||||
template<> struct hash<int>;
|
||||
template<> struct hash<unsigned int>;
|
||||
template<> struct hash<long>;
|
||||
template<> struct hash<unsigned long>;
|
||||
template<> struct hash<long long>;
|
||||
template<> struct hash<unsigned long long>;
|
||||
template<> struct hash<float>;
|
||||
template<> struct hash<double>;
|
||||
template<> struct hash<long double>;
|
||||
template<> struct hash<std::string>;
|
||||
template<> struct hash<std::wstring>;
|
||||
template<> struct hash<std::u16string>;
|
||||
template<> struct hash<std::u32string>;
|
||||
template<> struct hash<std::type_index>;
|
||||
|
||||
template<typename T> struct hash<T*>;
|
||||
|
||||
// Support functions (Boost extension).
|
||||
template<typename T>
|
||||
void hash_combine(size_t &, T const&);
|
||||
|
||||
template<typename It>
|
||||
std::size_t hash_range(It, It);
|
||||
|
||||
template<typename It>
|
||||
void hash_range(std::size_t&, It, It);
|
||||
|
||||
// Overloadable hash implementation (Boost extension).
|
||||
std::size_t hash_value(bool);
|
||||
std::size_t hash_value(char);
|
||||
std::size_t hash_value(signed char);
|
||||
std::size_t hash_value(unsigned char);
|
||||
std::size_t hash_value(wchar_t);
|
||||
std::size_t hash_value(char16_t);
|
||||
std::size_t hash_value(char32_t);
|
||||
std::size_t hash_value(short);
|
||||
std::size_t hash_value(unsigned short);
|
||||
std::size_t hash_value(int);
|
||||
std::size_t hash_value(unsigned int);
|
||||
std::size_t hash_value(long);
|
||||
std::size_t hash_value(unsigned long);
|
||||
std::size_t hash_value(long long);
|
||||
std::size_t hash_value(unsigned long long);
|
||||
std::size_t hash_value(float);
|
||||
std::size_t hash_value(double);
|
||||
std::size_t hash_value(long double);
|
||||
|
||||
template<typename T>
|
||||
std::size_t hash_value(T* const&);
|
||||
|
||||
template<typename T, unsigned N>
|
||||
std::size_t hash_value(T (&val)[N]);
|
||||
|
||||
template<typename T, unsigned N>
|
||||
std::size_t hash_value(const T (&val)[N]);
|
||||
|
||||
template<typename Ch, typename A>
|
||||
std::size_t hash_value(std::basic_string<Ch, std::char_traits<Ch>, A> const&);
|
||||
|
||||
template<typename A, typename B>
|
||||
std::size_t hash_value(std::pair<A, B> const&);
|
||||
|
||||
template<typename T, typename A>
|
||||
std::size_t hash_value(std::vector<T, A> const&);
|
||||
|
||||
template<typename T, typename A>
|
||||
std::size_t hash_value(std::list<T, A> const&);
|
||||
|
||||
template<typename T, typename A>
|
||||
std::size_t hash_value(std::deque<T, A> const&);
|
||||
|
||||
template<typename K, typename C, typename A>
|
||||
std::size_t hash_value(std::set<K, C, A> const&);
|
||||
|
||||
template<typename K, typename C, typename A>
|
||||
std::size_t hash_value(std::multiset<K, C, A> const&);
|
||||
|
||||
template<typename K, typename T, typename C, typename A>
|
||||
std::size_t hash_value(std::map<K, T, C, A> const&);
|
||||
|
||||
template<typename K, typename T, typename C, typename A>
|
||||
std::size_t hash_value(std::multimap<K, T, C, A> const&);
|
||||
|
||||
template<typename T> std::size_t hash_value(std::complex<T> const&);
|
||||
std::size_t hash_value(std::type_index);
|
||||
|
||||
template<typename T, std::size_t N>
|
||||
std::size_t hash_value(std::array<T, N> const&);
|
||||
|
||||
template<typename... T>
|
||||
std::size_t hash_value(std::tuple<T...>);
|
||||
}
|
||||
----
|
||||
|
||||
== Struct template hash
|
||||
|
||||
=== hash
|
||||
|
||||
`boost::hash` — A http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2005/n1836.pdf[TR1] compliant hash function object.
|
||||
|
||||
==== Synopsis
|
||||
|
||||
[source]
|
||||
----
|
||||
// #include <boost/container_hash/hash.hpp>
|
||||
|
||||
template<typename T>
|
||||
struct hash : public std::unary_function<T, std::size_t> {
|
||||
std::size_t operator()(T const&) const;
|
||||
};
|
||||
----
|
||||
|
||||
==== Description
|
||||
|
||||
[source]
|
||||
----
|
||||
std::size_t operator()(T const& val) const;
|
||||
----
|
||||
|
||||
[horizontal]
|
||||
Returns:: `hash_value(val)`
|
||||
|
||||
Notes:: The call to `hash_value` is unqualified, so that custom overloads can be found via argument dependent lookup.
|
||||
+
|
||||
This is not defined when the macro `BOOST_HASH_NO_EXTENSIONS` is defined. The specializations are still defined, so only the specializations required by TR1 are defined.
|
||||
+
|
||||
Forward declared in `<boost/container_hash/hash_fwd.hpp>`
|
||||
+
|
||||
This hash function is not intended for general use, and isn't guaranteed to be equal during separate runs of a program - so please don't use it for any persistent storage or communication.
|
||||
|
||||
Throws:: Only throws if `hash_value(T)` throws.
|
||||
|
||||
== Specializations
|
||||
|
||||
`boost::hash<T>`
|
||||
|
||||
=== Synopsis
|
||||
|
||||
[source]
|
||||
----
|
||||
// #include <boost/container_hash/hash.hpp>
|
||||
|
||||
struct hash<T> {
|
||||
std::size_t operator()(T const&) const;
|
||||
};
|
||||
----
|
||||
|
||||
=== Description
|
||||
|
||||
[source]
|
||||
----
|
||||
std::size_t operator()(T const val) const;
|
||||
----
|
||||
|
||||
[horizontal]
|
||||
Returns:: Unspecified in TR1, except that equal arguments yield the same result.
|
||||
+
|
||||
`hash_value(val)` in Boost.
|
||||
|
||||
[horizontal]
|
||||
Throws:: Doesn't throw
|
||||
|
||||
== Support functions (Boost extension).
|
||||
|
||||
=== hash_combine
|
||||
|
||||
[source]
|
||||
----
|
||||
template<typename T>
|
||||
void hash_combine(size_t &, T const&);
|
||||
----
|
||||
|
||||
Called repeatedly to incrementally create a hash value from several variables.
|
||||
|
||||
[horizontal]
|
||||
Effects:: Updates seed with a new hash value generated by combining it with the result of `hash_value(v)`. Will always produce the same result for the same combination of seed and `hash_value(v)` during the single run of a program.
|
||||
|
||||
[horizontal]
|
||||
Notes:: `hash_value` is called without qualification, so that overloads can be found via ADL. +
|
||||
+
|
||||
This is an extension to TR1 +
|
||||
+
|
||||
Forward declared in `<boost/container_hash/hash_fwd.hpp>` +
|
||||
+
|
||||
This hash function is not intended for general use, and isn't guaranteed to be equal during separate runs of a program - so please don't use it for any persistent storage or communication.
|
||||
|
||||
[horizontal]
|
||||
Throws:: Only throws if `hash_value(T)` throws. Strong exception safety, as long as `hash_value(T)` also has strong exception safety.
|
||||
|
||||
=== hash_range
|
||||
|
||||
[source]
|
||||
----
|
||||
template<typename It>
|
||||
std::size_t hash_range(It, It);
|
||||
|
||||
template<typename It>
|
||||
void hash_range(std::size_t&, It, It);
|
||||
----
|
||||
|
||||
Calculate the combined hash value of the elements of an iterator range.
|
||||
|
||||
[horizontal]
|
||||
Effects:: For the two argument overload:
|
||||
+
|
||||
[source]
|
||||
----
|
||||
size_t seed = 0;
|
||||
|
||||
for(; first != last; ++first)
|
||||
{
|
||||
hash_combine(seed, *first);
|
||||
}
|
||||
return seed;
|
||||
----
|
||||
+
|
||||
For the three arguments overload:
|
||||
+
|
||||
[source]
|
||||
----
|
||||
for(; first != last; ++first)
|
||||
{
|
||||
hash_combine(seed, *first);
|
||||
}
|
||||
----
|
||||
|
||||
[horizontal]
|
||||
Notes:: `hash_range` is sensitive to the order of the elements so it wouldn't be appropriate to use this with an unordered container.
|
||||
+
|
||||
This is an extension to TR1
|
||||
+
|
||||
Forward declared in `<boost/container_hash/hash_fwd.hpp>`
|
||||
+
|
||||
This hash function is not intended for general use, and isn't guaranteed to be equal during separate runs of a program - so please don't use it for any persistent storage or communication.
|
||||
|
||||
[horizontal]
|
||||
Throws:: Only throws if `hash_value(std::iterator_traits<It>::value_type)` throws. `hash_range(std::size_t&, It, It)` has basic exception safety as long as `hash_value(std::iterator_traits<It>::value_type)` has basic exception safety.
|
||||
|
||||
== Overloadable hash implementation (Boost extension).
|
||||
|
||||
=== hash_value
|
||||
|
||||
[source]
|
||||
----
|
||||
std::size_t hash_value(bool val);
|
||||
std::size_t hash_value(char val);
|
||||
std::size_t hash_value(signed char val);
|
||||
std::size_t hash_value(unsigned char val);
|
||||
std::size_t hash_value(wchar_t val);
|
||||
std::size_t hash_value(char16_t val);
|
||||
std::size_t hash_value(char32_t val);
|
||||
std::size_t hash_value(short val);
|
||||
std::size_t hash_value(unsigned short val);
|
||||
std::size_t hash_value(int val);
|
||||
std::size_t hash_value(unsigned int val);
|
||||
std::size_t hash_value(long val);
|
||||
std::size_t hash_value(unsigned long val);
|
||||
std::size_t hash_value(long long val);
|
||||
std::size_t hash_value(unsigned long long val);
|
||||
std::size_t hash_value(float val);
|
||||
std::size_t hash_value(double val);
|
||||
std::size_t hash_value(long double val);
|
||||
|
||||
template<typename T> std::size_t hash_value(T* const& val);
|
||||
|
||||
template<typename T, unsigned N> std::size_t hash_value(T (&val)[N]);
|
||||
template<typename T, unsigned N> std::size_t hash_value(const T (&val)[N]);
|
||||
|
||||
template<typename Ch, typename A>
|
||||
std::size_t hash_value(std::basic_string<Ch, std::char_traits<Ch>, A> const& val);
|
||||
template<typename A, typename B>
|
||||
std::size_t hash_value(std::pair<A, B> const& val);
|
||||
template<typename T, typename A>
|
||||
std::size_t hash_value(std::vector<T, A> const& val);
|
||||
template<typename T, typename A>
|
||||
std::size_t hash_value(std::list<T, A> const& val);
|
||||
template<typename T, typename A>
|
||||
std::size_t hash_value(std::deque<T, A> const& val);
|
||||
template<typename K, typename C, typename A>
|
||||
std::size_t hash_value(std::set<K, C, A> const& val);
|
||||
template<typename K, typename C, typename A>
|
||||
std::size_t hash_value(std::multiset<K, C, A> const& val);
|
||||
template<typename K, typename T, typename C, typename A>
|
||||
std::size_t hash_value(std::map<K, T, C, A> const& val);
|
||||
template<typename K, typename T, typename C, typename A>
|
||||
std::size_t hash_value(std::multimap<K, T, C, A> const& val);
|
||||
template<typename T> std::size_t hash_value(std::complex<T> const& val);
|
||||
std::size_t hash_value(std::type_index val);
|
||||
template<typename T, std::size_t N>
|
||||
std::size_t hash_value(std::array<T, N> const& val);
|
||||
template<typename... T>
|
||||
std::size_t hash_value(std::tuple<T...> val);
|
||||
----
|
||||
|
||||
Implementation of the hash function.
|
||||
|
||||
Generally shouldn't be called directly by users, instead they should use `boost::hash`, `boost::hash_range` or `boost::hash_combine` which call `hash_value` without namespace qualification so that overloads for custom types are found via ADL.
|
||||
|
||||
[horizontal]
|
||||
Notes:: This is an extension to TR1
|
||||
+
|
||||
This hash function is not intended for general use, and isn't guaranteed to be equal during separate runs of a program - so please don't use it for any persistent storage or communication.
|
||||
|
||||
[horizontal]
|
||||
Throws:: Only throws if a user supplied version of `hash_value` throws for an element of a container, or one of the types stored in a pair.
|
||||
|
||||
[vertical]
|
||||
Returns::
|
||||
+
|
||||
[cols="1,1", frame=all, grid=rows]
|
||||
|===
|
||||
|Types |Returns
|
||||
|
||||
|`bool`, `char`, `signed char`, `unsigned char`, `wchar_t`, `char16_t`, `char32_t`, `short`, `unsigned short`, `int`, `unsigned int`, `long`, `unsigned long`
|
||||
|val
|
||||
|
||||
|`long long`, `unsigned long long`
|
||||
|val when `abs(val) \<= std::numeric_limits<std::size_t>::max()`.
|
||||
|
||||
|`float`, `double`, `long double`
|
||||
|An unspecified value, except that equal arguments shall yield the same result.
|
||||
|
||||
|`T*`
|
||||
|An unspecified value, except that equal arguments shall yield the same result.
|
||||
|
||||
|`T val[N]`, `const T val[N]`
|
||||
|`hash_range(val, val+N)`
|
||||
|
||||
|`std:basic_string<Ch, std::char_traits<Ch>, A>`, `std::vector<T, A>`, `std::list<T, A>`, `std::deque<T, A>`, `std::set<K, C, A>`, `std::multiset<K, C, A>`, `std::map<K, T, C, A>`, `std::multimap<K, T, C, A>`, `std::array<T, N>`
|
||||
|`hash_range(val.begin(), val.end())`
|
||||
|
||||
|`std::pair<A, B>`
|
||||
a|
|
||||
|
||||
[source]
|
||||
----
|
||||
size_t seed = 0;
|
||||
hash_combine(seed, val.first);
|
||||
hash_combine(seed, val.second);
|
||||
return seed;
|
||||
----
|
||||
|
||||
|`std::tuple<T...>`
|
||||
a|
|
||||
|
||||
[source]
|
||||
----
|
||||
size_t seed = 0;
|
||||
hash_combine(seed, get<0>(val));
|
||||
hash_combine(seed, get<1>(val));
|
||||
// ....
|
||||
return seed;
|
||||
----
|
||||
|
||||
|`std::complex<T>`
|
||||
|When T is a built in type and `val.imag() == 0`, the result is equal to `hash_value(val.real())`. Otherwise an unspecified value, except that equal arguments shall yield the same result.
|
||||
|
||||
|`std::type_index`
|
||||
|`val.hash_code()`
|
||||
|
||||
|===
|
14
doc/hash/thanks.adoc
Normal file
14
doc/hash/thanks.adoc
Normal file
@ -0,0 +1,14 @@
|
||||
[#thanks]
|
||||
= Acknowledgements
|
||||
|
||||
:idprefix: thanks_
|
||||
|
||||
This library is based on the design by Peter Dimov. During the initial development Joaquín M López Muñoz made many useful suggestions and contributed fixes.
|
||||
|
||||
The formal review was managed by Thorsten Ottosen, and the library reviewed by: David Abrahams, Alberto Barbati, Topher Cooper, Caleb Epstein, Dave Harris, Chris Jefferson, Bronek Kozicki, John Maddock, Tobias Swinger, Jaap Suter, Rob Stewart and Pavel Vozenilek. Since then, further constructive criticism has been made by Daniel Krügler, Alexander Nasonov and 沈慧峰.
|
||||
|
||||
The implementation of the hash function for pointers is based on suggestions made by Alberto Barbati and Dave Harris. Dave Harris also suggested an important improvement to `boost::hash_combine` that was taken up.
|
||||
|
||||
Some useful improvements to the floating point hash algorithm were suggested by Daniel Krügler.
|
||||
|
||||
The original implementation came from Jeremy B. Maitin-Shepard's hash table library, although this is a complete rewrite.
|
48
doc/hash/tutorial.adoc
Normal file
48
doc/hash/tutorial.adoc
Normal file
@ -0,0 +1,48 @@
|
||||
[#tutorial]
|
||||
= Tutorial
|
||||
|
||||
:idprefix: tutorial_
|
||||
|
||||
When using a hash index with link:../../../multi_index/index.html[Boost.MultiIndex], you don't need to do anything to use `boost::hash` as it uses it by default. To find out how to use a user-defined type, read the <<custom,section on extending boost::hash for a custom data type>>.
|
||||
|
||||
If your standard library supplies its own implementation of the unordered associative containers and you wish to use `boost::hash`, just use an extra template parameter:
|
||||
|
||||
[source]
|
||||
----
|
||||
std::unordered_multiset<int, boost::hash<int> >
|
||||
set_of_ints;
|
||||
|
||||
std::unordered_set<std::pair<int, int>, boost::hash<std::pair<int, int> > >
|
||||
set_of_pairs;
|
||||
|
||||
std::unordered_map<int, std::string, boost::hash<int> > map_int_to_string;
|
||||
----
|
||||
|
||||
To use `boost::hash` directly, create an instance and call it as a function:
|
||||
|
||||
[source]
|
||||
----
|
||||
#include <boost/container_hash/hash.hpp>
|
||||
|
||||
int main()
|
||||
{
|
||||
boost::hash<std::string> string_hash;
|
||||
|
||||
std::size_t h = string_hash("Hash me");
|
||||
}
|
||||
----
|
||||
|
||||
For an example of generic use, here is a function to generate a vector containing the hashes of the elements of a container:
|
||||
|
||||
[source]
|
||||
----
|
||||
template <class Container>
|
||||
std::vector<std::size_t> get_hashes(Container const& x)
|
||||
{
|
||||
std::vector<std::size_t> hashes;
|
||||
std::transform(x.begin(), x.end(), std::back_inserter(hashes),
|
||||
boost::hash<typename Container::value_type>());
|
||||
|
||||
return hashes;
|
||||
}
|
||||
----
|
9
examples/Jamfile.v2
Normal file
9
examples/Jamfile.v2
Normal file
@ -0,0 +1,9 @@
|
||||
|
||||
# Copyright Daniel James 2005. Use, modification, and distribution are
|
||||
# subject to 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)
|
||||
|
||||
run books.cpp ;
|
||||
run point.cpp ;
|
||||
run portable.cpp ;
|
||||
run template.cpp : : : <toolset>msvc-8.0:<build>no ;
|
51
examples/books.cpp
Normal file
51
examples/books.cpp
Normal file
@ -0,0 +1,51 @@
|
||||
|
||||
// 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)
|
||||
|
||||
#include "./books.hpp"
|
||||
#include <boost/container_hash/hash.hpp>
|
||||
#include <cassert>
|
||||
|
||||
// If std::unordered_set was available:
|
||||
//#include <unordered_set>
|
||||
|
||||
// This example illustrates how to use boost::hash with a custom hash function.
|
||||
// For full details, see the tutorial.
|
||||
|
||||
int main()
|
||||
{
|
||||
library::book knife(3458, "Zane Grey", "The Hash Knife Outfit");
|
||||
library::book dandelion(1354, "Paul J. Shanley", "Hash & Dandelion Greens");
|
||||
|
||||
boost::hash<library::book> book_hasher;
|
||||
std::size_t knife_hash_value = book_hasher(knife);
|
||||
(void)knife_hash_value; // suppress unused variable warning
|
||||
|
||||
// If std::unordered_set was available:
|
||||
//
|
||||
//std::unordered_set<library::book, boost::hash<library::book> > books;
|
||||
//books.insert(knife);
|
||||
//books.insert(library::book(2443, "Lindgren, Torgny", "Hash"));
|
||||
//books.insert(library::book(1953, "Snyder, Bernadette M.",
|
||||
// "Heavenly Hash: A Tasty Mix of a Mother's Meditations"));
|
||||
|
||||
//assert(books.find(knife) != books.end());
|
||||
//assert(books.find(dandelion) == books.end());
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
namespace library
|
||||
{
|
||||
bool operator==(book const& a, book const& b)
|
||||
{
|
||||
return a.id == b.id;
|
||||
}
|
||||
|
||||
std::size_t hash_value(book const& b)
|
||||
{
|
||||
boost::hash<int> hasher;
|
||||
return hasher(b.id);
|
||||
}
|
||||
}
|
26
examples/books.hpp
Normal file
26
examples/books.hpp
Normal file
@ -0,0 +1,26 @@
|
||||
|
||||
// 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)
|
||||
|
||||
// This example illustrates how to use boost::hash with a custom hash function.
|
||||
// The implementation is contained in books.cpp
|
||||
|
||||
#include <cstddef>
|
||||
#include <string>
|
||||
|
||||
namespace library
|
||||
{
|
||||
struct book
|
||||
{
|
||||
int id;
|
||||
std::string author;
|
||||
std::string title;
|
||||
|
||||
book(int i, std::string const& a, std::string const& t)
|
||||
: id(i), author(a), title(t) {}
|
||||
};
|
||||
|
||||
bool operator==(book const&, book const&);
|
||||
std::size_t hash_value(book const&);
|
||||
}
|
59
examples/point.cpp
Normal file
59
examples/point.cpp
Normal file
@ -0,0 +1,59 @@
|
||||
|
||||
// Copyright 2005 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)
|
||||
|
||||
// Force use of assert.
|
||||
#if defined(NDEBUG)
|
||||
#undef NDEBUG
|
||||
#endif
|
||||
|
||||
#include <boost/container_hash/hash.hpp>
|
||||
#include <cassert>
|
||||
|
||||
// This example illustrates how to use boost::hash_combine to generate a hash
|
||||
// value from the different members of a class. For full details see the hash
|
||||
// tutorial.
|
||||
|
||||
class point
|
||||
{
|
||||
int x;
|
||||
int y;
|
||||
public:
|
||||
point() : x(0), y(0) {}
|
||||
point(int x, int y) : x(x), y(y) {}
|
||||
|
||||
bool operator==(point const& other) const
|
||||
{
|
||||
return x == other.x && y == other.y;
|
||||
}
|
||||
|
||||
friend std::size_t hash_value(point const& p)
|
||||
{
|
||||
std::size_t seed = 0;
|
||||
boost::hash_combine(seed, p.x);
|
||||
boost::hash_combine(seed, p.y);
|
||||
|
||||
return seed;
|
||||
}
|
||||
};
|
||||
|
||||
int main()
|
||||
{
|
||||
boost::hash<point> point_hasher;
|
||||
|
||||
point p1(0, 0);
|
||||
point p2(1, 2);
|
||||
point p3(4, 1);
|
||||
point p4 = p1;
|
||||
|
||||
assert(point_hasher(p1) == point_hasher(p4));
|
||||
|
||||
// These tests could legally fail, but if they did it'd be a pretty bad
|
||||
// hash function.
|
||||
assert(point_hasher(p1) != point_hasher(p2));
|
||||
assert(point_hasher(p1) != point_hasher(p3));
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
59
examples/portable.cpp
Normal file
59
examples/portable.cpp
Normal file
@ -0,0 +1,59 @@
|
||||
|
||||
// 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)
|
||||
|
||||
// Force use of assert.
|
||||
#if defined(NDEBUG)
|
||||
#undef NDEBUG
|
||||
#endif
|
||||
|
||||
#include <boost/container_hash/hash.hpp>
|
||||
#include <cassert>
|
||||
|
||||
// This example illustrates how to customise boost::hash portably, so that
|
||||
// it'll work on both compilers that don't implement argument dependent lookup
|
||||
// and compilers that implement strict two-phase template instantiation.
|
||||
|
||||
namespace foo
|
||||
{
|
||||
template <class T>
|
||||
class custom_type
|
||||
{
|
||||
T value;
|
||||
public:
|
||||
custom_type(T x) : value(x) {}
|
||||
|
||||
std::size_t hash() const
|
||||
{
|
||||
boost::hash<T> hasher;
|
||||
return hasher(value);
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
#ifdef BOOST_NO_ARGUMENT_DEPENDENT_LOOKUP
|
||||
namespace boost
|
||||
#else
|
||||
namespace foo
|
||||
#endif
|
||||
{
|
||||
template <class T>
|
||||
std::size_t hash_value(foo::custom_type<T> x)
|
||||
{
|
||||
return x.hash();
|
||||
}
|
||||
}
|
||||
|
||||
int main()
|
||||
{
|
||||
foo::custom_type<int> x(1), y(2), z(1);
|
||||
|
||||
boost::hash<foo::custom_type<int> > hasher;
|
||||
|
||||
assert(hasher(x) == hasher(x));
|
||||
assert(hasher(x) != hasher(y));
|
||||
assert(hasher(x) == hasher(z));
|
||||
|
||||
return 0;
|
||||
}
|
18
examples/template.cpp
Normal file
18
examples/template.cpp
Normal file
@ -0,0 +1,18 @@
|
||||
|
||||
// Copyright 2012 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 "template.hpp"
|
||||
#include <cassert>
|
||||
#include <boost/unordered_set.hpp>
|
||||
|
||||
int main()
|
||||
{
|
||||
typedef my_pair<int, float> pair;
|
||||
boost::unordered_set<pair> pair_set;
|
||||
pair_set.emplace(10, 0.5f);
|
||||
|
||||
assert(pair_set.find(pair(10, 0.5f)) != pair_set.end());
|
||||
assert(pair_set.find(pair(10, 0.6f)) == pair_set.end());
|
||||
}
|
36
examples/template.hpp
Normal file
36
examples/template.hpp
Normal file
@ -0,0 +1,36 @@
|
||||
|
||||
// Copyright 2012 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)
|
||||
|
||||
// This is an example of how to write a hash function for a template
|
||||
// class.
|
||||
|
||||
#include <boost/container_hash/hash_fwd.hpp>
|
||||
|
||||
template <typename A, typename B>
|
||||
class my_pair
|
||||
{
|
||||
A value1;
|
||||
B value2;
|
||||
public:
|
||||
my_pair(A const& v1, B const& v2)
|
||||
: value1(v1), value2(v2)
|
||||
{}
|
||||
|
||||
bool operator==(my_pair const& other) const
|
||||
{
|
||||
return value1 == other.value1 &&
|
||||
value2 == other.value2;
|
||||
}
|
||||
|
||||
friend std::size_t hash_value(my_pair const& p)
|
||||
{
|
||||
std::size_t seed = 0;
|
||||
boost::hash_combine(seed, p.value1);
|
||||
boost::hash_combine(seed, p.value2);
|
||||
|
||||
return seed;
|
||||
}
|
||||
};
|
||||
|
133
include/boost/container_hash/detail/hash_tuple.hpp
Normal file
133
include/boost/container_hash/detail/hash_tuple.hpp
Normal file
@ -0,0 +1,133 @@
|
||||
// Copyright 2005-2009 Daniel James.
|
||||
// Copyright 2021 Peter Dimov.
|
||||
// Distributed under the Boost Software License, Version 1.0.
|
||||
// https://www.boost.org/LICENSE_1_0.txt
|
||||
|
||||
#ifndef BOOST_HASH_DETAIL_HASH_TUPLE_LIKE_HPP
|
||||
#define BOOST_HASH_DETAIL_HASH_TUPLE_LIKE_HPP
|
||||
|
||||
#include <boost/container_hash/hash_fwd.hpp>
|
||||
#include <boost/type_traits/enable_if.hpp>
|
||||
#include <boost/config.hpp>
|
||||
|
||||
#if defined(BOOST_NO_CXX11_HDR_TUPLE)
|
||||
|
||||
// no support
|
||||
|
||||
#else
|
||||
|
||||
#include <tuple>
|
||||
|
||||
namespace boost
|
||||
{
|
||||
namespace hash_detail
|
||||
{
|
||||
|
||||
template <std::size_t I, typename T>
|
||||
inline typename boost::enable_if_<(I == std::tuple_size<T>::value),
|
||||
void>::type
|
||||
hash_combine_tuple(std::size_t&, T const&)
|
||||
{
|
||||
}
|
||||
|
||||
template <std::size_t I, typename T>
|
||||
inline typename boost::enable_if_<(I < std::tuple_size<T>::value),
|
||||
void>::type
|
||||
hash_combine_tuple(std::size_t& seed, T const& v)
|
||||
{
|
||||
boost::hash_combine(seed, std::get<I>(v));
|
||||
boost::hash_detail::hash_combine_tuple<I + 1>(seed, v);
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
inline std::size_t hash_tuple(T const& v)
|
||||
{
|
||||
std::size_t seed = 0;
|
||||
boost::hash_detail::hash_combine_tuple<0>(seed, v);
|
||||
return seed;
|
||||
}
|
||||
|
||||
} // namespace hash_detail
|
||||
|
||||
#if !defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES)
|
||||
|
||||
template <typename... T>
|
||||
inline std::size_t hash_value(std::tuple<T...> const& v)
|
||||
{
|
||||
return boost::hash_detail::hash_tuple(v);
|
||||
}
|
||||
|
||||
#else
|
||||
|
||||
inline std::size_t hash_value(std::tuple<> const& v)
|
||||
{
|
||||
return boost::hash_detail::hash_tuple(v);
|
||||
}
|
||||
|
||||
template<typename A0>
|
||||
inline std::size_t hash_value(std::tuple<A0> const& v)
|
||||
{
|
||||
return boost::hash_detail::hash_tuple(v);
|
||||
}
|
||||
|
||||
template<typename A0, typename A1>
|
||||
inline std::size_t hash_value(std::tuple<A0, A1> const& v)
|
||||
{
|
||||
return boost::hash_detail::hash_tuple(v);
|
||||
}
|
||||
|
||||
template<typename A0, typename A1, typename A2>
|
||||
inline std::size_t hash_value(std::tuple<A0, A1, A2> const& v)
|
||||
{
|
||||
return boost::hash_detail::hash_tuple(v);
|
||||
}
|
||||
|
||||
template<typename A0, typename A1, typename A2, typename A3>
|
||||
inline std::size_t hash_value(std::tuple<A0, A1, A2, A3> const& v)
|
||||
{
|
||||
return boost::hash_detail::hash_tuple(v);
|
||||
}
|
||||
|
||||
template<typename A0, typename A1, typename A2, typename A3, typename A4>
|
||||
inline std::size_t hash_value(std::tuple<A0, A1, A2, A3, A4> const& v)
|
||||
{
|
||||
return boost::hash_detail::hash_tuple(v);
|
||||
}
|
||||
|
||||
template<typename A0, typename A1, typename A2, typename A3, typename A4, typename A5>
|
||||
inline std::size_t hash_value(std::tuple<A0, A1, A2, A3, A4, A5> const& v)
|
||||
{
|
||||
return boost::hash_detail::hash_tuple(v);
|
||||
}
|
||||
|
||||
template<typename A0, typename A1, typename A2, typename A3, typename A4, typename A5, typename A6>
|
||||
inline std::size_t hash_value(std::tuple<A0, A1, A2, A3, A4, A5, A6> const& v)
|
||||
{
|
||||
return boost::hash_detail::hash_tuple(v);
|
||||
}
|
||||
|
||||
template<typename A0, typename A1, typename A2, typename A3, typename A4, typename A5, typename A6, typename A7>
|
||||
inline std::size_t hash_value(std::tuple<A0, A1, A2, A3, A4, A5, A6, A7> const& v)
|
||||
{
|
||||
return boost::hash_detail::hash_tuple(v);
|
||||
}
|
||||
|
||||
template<typename A0, typename A1, typename A2, typename A3, typename A4, typename A5, typename A6, typename A7, typename A8>
|
||||
inline std::size_t hash_value(std::tuple<A0, A1, A2, A3, A4, A5, A6, A7, A8> const& v)
|
||||
{
|
||||
return boost::hash_detail::hash_tuple(v);
|
||||
}
|
||||
|
||||
template<typename A0, typename A1, typename A2, typename A3, typename A4, typename A5, typename A6, typename A7, typename A8, typename A9>
|
||||
inline std::size_t hash_value(std::tuple<A0, A1, A2, A3, A4, A5, A6, A7, A8, A9> const& v)
|
||||
{
|
||||
return boost::hash_detail::hash_tuple(v);
|
||||
}
|
||||
|
||||
#endif // #if !defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES)
|
||||
|
||||
} // namespace boost
|
||||
|
||||
#endif // #if defined(BOOST_NO_CXX11_HDR_TUPLE)
|
||||
|
||||
#endif // #ifndef BOOST_HASH_DETAIL_HASH_TUPLE_LIKE_HPP
|
81
include/boost/container_hash/detail/is_contiguous_range.hpp
Normal file
81
include/boost/container_hash/detail/is_contiguous_range.hpp
Normal file
@ -0,0 +1,81 @@
|
||||
// Copyright 2017, 2018 Peter Dimov.
|
||||
// Distributed under the Boost Software License, Version 1.0.
|
||||
// https://www.boost.org/LICENSE_1_0.txt
|
||||
|
||||
#ifndef BOOST_HASH_DETAIL_IS_CONTIGUOUS_RANGE_HPP_INCLUDED
|
||||
#define BOOST_HASH_DETAIL_IS_CONTIGUOUS_RANGE_HPP_INCLUDED
|
||||
|
||||
#include <boost/type_traits/integral_constant.hpp>
|
||||
#include <boost/config.hpp>
|
||||
#include <boost/config/workaround.hpp>
|
||||
|
||||
#if !defined(BOOST_NO_CXX11_DECLTYPE) && !defined(BOOST_NO_SFINAE_EXPR) && !BOOST_WORKAROUND(BOOST_GCC, < 40700)
|
||||
|
||||
#include <boost/type_traits/is_integral.hpp>
|
||||
#include <boost/type_traits/declval.hpp>
|
||||
#include <boost/type_traits/is_same.hpp>
|
||||
#include <iterator>
|
||||
|
||||
namespace boost
|
||||
{
|
||||
namespace hash_detail
|
||||
{
|
||||
|
||||
template<class It, class T, class S>
|
||||
integral_constant< bool, is_same<typename std::iterator_traits<It>::value_type, T>::value && is_integral<S>::value >
|
||||
is_contiguous_range_check( It first, It last, T const*, T const*, S );
|
||||
|
||||
template<class T> decltype( is_contiguous_range_check( declval<T const&>().begin(), declval<T const&>().end(), declval<T const&>().data(), declval<T const&>().data() + declval<T const&>().size(), declval<T const&>().size() ) ) is_contiguous_range_( int );
|
||||
template<class T> false_type is_contiguous_range_( ... );
|
||||
|
||||
template<class T> struct is_contiguous_range: decltype( hash_detail::is_contiguous_range_<T>( 0 ) )
|
||||
{
|
||||
};
|
||||
|
||||
} // namespace hash_detail
|
||||
} // namespace boost
|
||||
|
||||
#else // !defined(BOOST_NO_CXX11_DECLTYPE) && !defined(BOOST_NO_SFINAE_EXPR)
|
||||
|
||||
#include <cstddef>
|
||||
#include <vector>
|
||||
#include <string>
|
||||
#if !defined(BOOST_NO_CXX11_HDR_ARRAY)
|
||||
#include <array>
|
||||
#endif
|
||||
|
||||
namespace boost
|
||||
{
|
||||
namespace hash_detail
|
||||
{
|
||||
|
||||
template<class T> struct is_contiguous_range: false_type
|
||||
{
|
||||
};
|
||||
|
||||
template<class E, class T, class A> struct is_contiguous_range< std::basic_string<E, T, A> >: true_type
|
||||
{
|
||||
};
|
||||
|
||||
template<class E, class T, class A> struct is_contiguous_range< std::basic_string<E, T, A> const >: true_type
|
||||
{
|
||||
};
|
||||
|
||||
#if !defined(BOOST_NO_CXX11_HDR_ARRAY)
|
||||
|
||||
template<class T, std::size_t N> struct is_contiguous_range< std::array<T, N> >: true_type
|
||||
{
|
||||
};
|
||||
|
||||
template<class T, std::size_t N> struct is_contiguous_range< std::array<T, N> const >: true_type
|
||||
{
|
||||
};
|
||||
|
||||
#endif
|
||||
|
||||
} // namespace hash_detail
|
||||
} // namespace boost
|
||||
|
||||
#endif // !defined(BOOST_NO_CXX11_DECLTYPE) && !defined(BOOST_NO_SFINAE_EXPR)
|
||||
|
||||
#endif // #ifndef BOOST_HASH_DETAIL_IS_CONTIGUOUS_RANGE_HPP_INCLUDED
|
57
include/boost/container_hash/detail/is_range.hpp
Normal file
57
include/boost/container_hash/detail/is_range.hpp
Normal file
@ -0,0 +1,57 @@
|
||||
// Copyright 2017 Peter Dimov.
|
||||
// Distributed under the Boost Software License, Version 1.0.
|
||||
// https://www.boost.org/LICENSE_1_0.txt
|
||||
|
||||
#ifndef BOOST_HASH_DETAIL_IS_RANGE_HPP_INCLUDED
|
||||
#define BOOST_HASH_DETAIL_IS_RANGE_HPP_INCLUDED
|
||||
|
||||
#include <boost/type_traits/integral_constant.hpp>
|
||||
#include <boost/type_traits/is_integral.hpp>
|
||||
#include <boost/type_traits/declval.hpp>
|
||||
#include <boost/type_traits/is_same.hpp>
|
||||
#include <boost/type_traits/remove_cv.hpp>
|
||||
#include <boost/config.hpp>
|
||||
#include <boost/config/workaround.hpp>
|
||||
#include <iterator>
|
||||
|
||||
namespace boost
|
||||
{
|
||||
namespace hash_detail
|
||||
{
|
||||
|
||||
#if !defined(BOOST_NO_CXX11_DECLTYPE) && !defined(BOOST_NO_SFINAE_EXPR) && !BOOST_WORKAROUND(BOOST_GCC, < 40700)
|
||||
|
||||
template<class T, class It>
|
||||
integral_constant< bool, !is_same<typename remove_cv<T>::type, typename std::iterator_traits<It>::value_type>::value >
|
||||
is_range_check( It first, It last );
|
||||
|
||||
template<class T> decltype( is_range_check<T>( declval<T const&>().begin(), declval<T const&>().end() ) ) is_range_( int );
|
||||
template<class T> false_type is_range_( ... );
|
||||
|
||||
template<class T> struct is_range: decltype( is_range_<T>( 0 ) )
|
||||
{
|
||||
};
|
||||
|
||||
#else
|
||||
|
||||
template<class T, class E = true_type> struct is_range_: false_type
|
||||
{
|
||||
};
|
||||
|
||||
template<class T> struct is_range_< T, integral_constant< bool,
|
||||
is_same<typename T::value_type, typename std::iterator_traits<typename T::const_iterator>::value_type>::value &&
|
||||
is_integral<typename T::size_type>::value
|
||||
> >: true_type
|
||||
{
|
||||
};
|
||||
|
||||
template<class T> struct is_range: is_range_<T>
|
||||
{
|
||||
};
|
||||
|
||||
#endif // !defined(BOOST_NO_CXX11_DECLTYPE) && !defined(BOOST_NO_SFINAE_EXPR)
|
||||
|
||||
} // namespace hash_detail
|
||||
} // namespace boost
|
||||
|
||||
#endif // #ifndef BOOST_HASH_DETAIL_IS_RANGE_HPP_INCLUDED
|
34
include/boost/container_hash/detail/is_unordered_range.hpp
Normal file
34
include/boost/container_hash/detail/is_unordered_range.hpp
Normal file
@ -0,0 +1,34 @@
|
||||
// Copyright 2017 Peter Dimov.
|
||||
// Distributed under the Boost Software License, Version 1.0.
|
||||
// https://www.boost.org/LICENSE_1_0.txt
|
||||
|
||||
#ifndef BOOST_HASH_DETAIL_IS_UNORDERED_RANGE_HPP_INCLUDED
|
||||
#define BOOST_HASH_DETAIL_IS_UNORDERED_RANGE_HPP_INCLUDED
|
||||
|
||||
#include <boost/container_hash/detail/is_range.hpp>
|
||||
#include <boost/type_traits/integral_constant.hpp>
|
||||
#include <boost/type_traits/is_same.hpp>
|
||||
|
||||
namespace boost
|
||||
{
|
||||
namespace hash_detail
|
||||
{
|
||||
|
||||
template<class T, class E = true_type> struct has_hasher_: false_type
|
||||
{
|
||||
};
|
||||
|
||||
template<class T> struct has_hasher_< T, integral_constant< bool,
|
||||
is_same<typename T::hasher, typename T::hasher>::value
|
||||
> >: true_type
|
||||
{
|
||||
};
|
||||
|
||||
template<class T> struct is_unordered_range: integral_constant< bool, is_range<T>::value && has_hasher_<T>::value >
|
||||
{
|
||||
};
|
||||
|
||||
} // namespace hash_detail
|
||||
} // namespace boost
|
||||
|
||||
#endif // #ifndef BOOST_HASH_DETAIL_IS_UNORDERED_RANGE_HPP_INCLUDED
|
19
include/boost/container_hash/detail/limits.hpp
Normal file
19
include/boost/container_hash/detail/limits.hpp
Normal file
@ -0,0 +1,19 @@
|
||||
// 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)
|
||||
|
||||
#ifndef BOOST_FUNCTIONAL_HASH_DETAIL_LIMITS_HEADER
|
||||
#define BOOST_FUNCTIONAL_HASH_DETAIL_LIMITS_HEADER
|
||||
|
||||
#include <limits>
|
||||
|
||||
namespace boost
|
||||
{
|
||||
namespace hash_detail
|
||||
{
|
||||
template <class T>
|
||||
struct limits : std::numeric_limits<T> {};
|
||||
}
|
||||
}
|
||||
|
||||
#endif // #ifndef BOOST_FUNCTIONAL_HASH_DETAIL_LIMITS_HEADER
|
10
include/boost/container_hash/extensions.hpp
Normal file
10
include/boost/container_hash/extensions.hpp
Normal file
@ -0,0 +1,10 @@
|
||||
// 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)
|
||||
|
||||
#ifndef BOOST_FUNCTIONAL_HASH_EXTENSIONS_HPP
|
||||
#define BOOST_FUNCTIONAL_HASH_EXTENSIONS_HPP
|
||||
|
||||
#include <boost/container_hash/hash.hpp>
|
||||
|
||||
#endif // #ifndef BOOST_FUNCTIONAL_HASH_EXTENSIONS_HPP
|
693
include/boost/container_hash/hash.hpp
Normal file
693
include/boost/container_hash/hash.hpp
Normal file
@ -0,0 +1,693 @@
|
||||
// Copyright 2005-2014 Daniel James.
|
||||
// Copyright 2021 Peter Dimov.
|
||||
// Distributed under the Boost Software License, Version 1.0.
|
||||
// https://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.
|
||||
|
||||
#ifndef BOOST_FUNCTIONAL_HASH_HASH_HPP
|
||||
#define BOOST_FUNCTIONAL_HASH_HASH_HPP
|
||||
|
||||
#include <boost/container_hash/hash_fwd.hpp>
|
||||
#include <boost/container_hash/detail/is_range.hpp>
|
||||
#include <boost/container_hash/detail/is_contiguous_range.hpp>
|
||||
#include <boost/container_hash/detail/is_unordered_range.hpp>
|
||||
#include <boost/container_hash/detail/hash_tuple.hpp>
|
||||
#include <boost/type_traits/is_enum.hpp>
|
||||
#include <boost/type_traits/is_integral.hpp>
|
||||
#include <boost/type_traits/is_floating_point.hpp>
|
||||
#include <boost/type_traits/is_signed.hpp>
|
||||
#include <boost/type_traits/is_unsigned.hpp>
|
||||
#include <boost/type_traits/make_unsigned.hpp>
|
||||
#include <boost/type_traits/enable_if.hpp>
|
||||
#include <boost/type_traits/conjunction.hpp>
|
||||
#include <boost/cstdint.hpp>
|
||||
#include <string>
|
||||
#include <iterator>
|
||||
#include <complex>
|
||||
#include <utility>
|
||||
#include <limits>
|
||||
#include <climits>
|
||||
#include <cstring>
|
||||
|
||||
#if !defined(BOOST_NO_CXX11_SMART_PTR)
|
||||
# include <memory>
|
||||
#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_NO_CXX17_HDR_OPTIONAL)
|
||||
#include <optional>
|
||||
#endif
|
||||
|
||||
#if !defined(BOOST_NO_CXX17_HDR_VARIANT)
|
||||
#include <variant>
|
||||
#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
|
||||
{
|
||||
|
||||
//
|
||||
// boost::hash_value
|
||||
//
|
||||
|
||||
// integral types
|
||||
|
||||
namespace hash_detail
|
||||
{
|
||||
template<class T,
|
||||
bool bigger_than_size_t = (sizeof(T) > sizeof(std::size_t)),
|
||||
bool is_unsigned = boost::is_unsigned<T>::value,
|
||||
std::size_t size_t_bits = sizeof(std::size_t) * CHAR_BIT,
|
||||
std::size_t type_bits = sizeof(T) * CHAR_BIT>
|
||||
struct hash_integral_impl;
|
||||
|
||||
template<class T, bool is_unsigned, std::size_t size_t_bits, std::size_t type_bits> struct hash_integral_impl<T, false, is_unsigned, size_t_bits, type_bits>
|
||||
{
|
||||
static std::size_t fn( T v )
|
||||
{
|
||||
return static_cast<std::size_t>( v );
|
||||
}
|
||||
};
|
||||
|
||||
template<class T, std::size_t size_t_bits, std::size_t type_bits> struct hash_integral_impl<T, true, false, size_t_bits, type_bits>
|
||||
{
|
||||
static std::size_t fn( T v )
|
||||
{
|
||||
typedef typename boost::make_unsigned<T>::type U;
|
||||
|
||||
if( v >= 0 )
|
||||
{
|
||||
return hash_integral_impl<U>::fn( static_cast<U>( v ) );
|
||||
}
|
||||
else
|
||||
{
|
||||
return ~hash_integral_impl<U>::fn( static_cast<U>( ~static_cast<U>( v ) ) );
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
template<class T> struct hash_integral_impl<T, true, true, 32, 64>
|
||||
{
|
||||
static std::size_t fn( T v )
|
||||
{
|
||||
std::size_t seed = 0;
|
||||
|
||||
seed ^= static_cast<std::size_t>( v >> 32 ) + ( seed << 6 ) + ( seed >> 2 );
|
||||
seed ^= static_cast<std::size_t>( v ) + ( seed << 6 ) + ( seed >> 2 );
|
||||
|
||||
return seed;
|
||||
}
|
||||
};
|
||||
|
||||
template<class T> struct hash_integral_impl<T, true, true, 32, 128>
|
||||
{
|
||||
static std::size_t fn( T v )
|
||||
{
|
||||
std::size_t seed = 0;
|
||||
|
||||
seed ^= static_cast<std::size_t>( v >> 96 ) + ( seed << 6 ) + ( seed >> 2 );
|
||||
seed ^= static_cast<std::size_t>( v >> 64 ) + ( seed << 6 ) + ( seed >> 2 );
|
||||
seed ^= static_cast<std::size_t>( v >> 32 ) + ( seed << 6 ) + ( seed >> 2 );
|
||||
seed ^= static_cast<std::size_t>( v ) + ( seed << 6 ) + ( seed >> 2 );
|
||||
|
||||
return seed;
|
||||
}
|
||||
};
|
||||
|
||||
template<class T> struct hash_integral_impl<T, true, true, 64, 128>
|
||||
{
|
||||
static std::size_t fn( T v )
|
||||
{
|
||||
std::size_t seed = 0;
|
||||
|
||||
seed ^= static_cast<std::size_t>( v >> 64 ) + ( seed << 6 ) + ( seed >> 2 );
|
||||
seed ^= static_cast<std::size_t>( v ) + ( seed << 6 ) + ( seed >> 2 );
|
||||
|
||||
return seed;
|
||||
}
|
||||
};
|
||||
|
||||
} // namespace hash_detail
|
||||
|
||||
template <typename T>
|
||||
typename boost::enable_if_<boost::is_integral<T>::value, std::size_t>::type
|
||||
hash_value( T v )
|
||||
{
|
||||
return hash_detail::hash_integral_impl<T>::fn( v );
|
||||
}
|
||||
|
||||
// enumeration types
|
||||
|
||||
template <typename T>
|
||||
typename boost::enable_if_<boost::is_enum<T>::value, std::size_t>::type
|
||||
hash_value( T v )
|
||||
{
|
||||
// This should in principle return the equivalent of
|
||||
//
|
||||
// boost::hash_value( to_underlying(v) );
|
||||
//
|
||||
// However, the C++03 implementation of underlying_type,
|
||||
//
|
||||
// conditional<is_signed<T>, make_signed<T>, make_unsigned<T>>::type::type
|
||||
//
|
||||
// generates a legitimate -Wconversion warning in is_signed,
|
||||
// because -1 is not a valid enum value when all the enumerators
|
||||
// are nonnegative.
|
||||
//
|
||||
// So the legacy implementation will have to do for now.
|
||||
|
||||
return static_cast<std::size_t>( v );
|
||||
}
|
||||
|
||||
// floating point types
|
||||
|
||||
namespace hash_detail
|
||||
{
|
||||
template<class T,
|
||||
std::size_t Bits = sizeof(T) * CHAR_BIT,
|
||||
int Digits = std::numeric_limits<T>::digits,
|
||||
std::size_t size_t_bits = sizeof(std::size_t) * CHAR_BIT>
|
||||
struct hash_float_impl;
|
||||
|
||||
// float
|
||||
template<class T, int Digits, std::size_t size_t_bits> struct hash_float_impl<T, 32, Digits, size_t_bits>
|
||||
{
|
||||
static std::size_t fn( T v )
|
||||
{
|
||||
boost::uint32_t w;
|
||||
std::memcpy( &w, &v, sizeof( v ) );
|
||||
|
||||
return w;
|
||||
}
|
||||
};
|
||||
|
||||
// double
|
||||
template<class T, int Digits> struct hash_float_impl<T, 64, Digits, 64>
|
||||
{
|
||||
static std::size_t fn( T v )
|
||||
{
|
||||
boost::uint64_t w;
|
||||
std::memcpy( &w, &v, sizeof( v ) );
|
||||
|
||||
return w;
|
||||
}
|
||||
};
|
||||
|
||||
template<class T, int Digits> struct hash_float_impl<T, 64, Digits, 32>
|
||||
{
|
||||
static std::size_t fn( T v )
|
||||
{
|
||||
boost::uint32_t w[ 2 ];
|
||||
std::memcpy( &w, &v, sizeof( v ) );
|
||||
|
||||
std::size_t seed = 0;
|
||||
|
||||
seed ^= static_cast<std::size_t>( w[0] ) + ( seed << 6 ) + ( seed >> 2 );
|
||||
seed ^= static_cast<std::size_t>( w[1] ) + ( seed << 6 ) + ( seed >> 2 );
|
||||
|
||||
return seed;
|
||||
}
|
||||
};
|
||||
|
||||
// 80 bit long double in 12 bytes
|
||||
template<class T> struct hash_float_impl<T, 96, 64, 64>
|
||||
{
|
||||
static std::size_t fn( T v )
|
||||
{
|
||||
boost::uint64_t w[ 2 ] = {};
|
||||
std::memcpy( &w, &v, 80 / CHAR_BIT );
|
||||
|
||||
std::size_t seed = 0;
|
||||
|
||||
seed ^= static_cast<std::size_t>( w[0] ) + ( seed << 6 ) + ( seed >> 2 );
|
||||
seed ^= static_cast<std::size_t>( w[1] ) + ( seed << 6 ) + ( seed >> 2 );
|
||||
|
||||
return seed;
|
||||
}
|
||||
};
|
||||
|
||||
template<class T> struct hash_float_impl<T, 96, 64, 32>
|
||||
{
|
||||
static std::size_t fn( T v )
|
||||
{
|
||||
boost::uint32_t w[ 3 ] = {};
|
||||
std::memcpy( &w, &v, 80 / CHAR_BIT );
|
||||
|
||||
std::size_t seed = 0;
|
||||
|
||||
seed ^= static_cast<std::size_t>( w[0] ) + ( seed << 6 ) + ( seed >> 2 );
|
||||
seed ^= static_cast<std::size_t>( w[1] ) + ( seed << 6 ) + ( seed >> 2 );
|
||||
seed ^= static_cast<std::size_t>( w[2] ) + ( seed << 6 ) + ( seed >> 2 );
|
||||
|
||||
return seed;
|
||||
}
|
||||
};
|
||||
|
||||
// 80 bit long double in 16 bytes
|
||||
template<class T> struct hash_float_impl<T, 128, 64, 64>
|
||||
{
|
||||
static std::size_t fn( T v )
|
||||
{
|
||||
boost::uint64_t w[ 2 ] = {};
|
||||
std::memcpy( &w, &v, 80 / CHAR_BIT );
|
||||
|
||||
std::size_t seed = 0;
|
||||
|
||||
seed ^= static_cast<std::size_t>( w[0] ) + ( seed << 6 ) + ( seed >> 2 );
|
||||
seed ^= static_cast<std::size_t>( w[1] ) + ( seed << 6 ) + ( seed >> 2 );
|
||||
|
||||
return seed;
|
||||
}
|
||||
};
|
||||
|
||||
template<class T> struct hash_float_impl<T, 128, 64, 32>
|
||||
{
|
||||
static std::size_t fn( T v )
|
||||
{
|
||||
boost::uint32_t w[ 3 ] = {};
|
||||
std::memcpy( &w, &v, 80 / CHAR_BIT );
|
||||
|
||||
std::size_t seed = 0;
|
||||
|
||||
seed ^= static_cast<std::size_t>( w[0] ) + ( seed << 6 ) + ( seed >> 2 );
|
||||
seed ^= static_cast<std::size_t>( w[1] ) + ( seed << 6 ) + ( seed >> 2 );
|
||||
seed ^= static_cast<std::size_t>( w[2] ) + ( seed << 6 ) + ( seed >> 2 );
|
||||
|
||||
return seed;
|
||||
}
|
||||
};
|
||||
|
||||
// 128 bit long double
|
||||
template<class T, int Digits> struct hash_float_impl<T, 128, Digits, 64>
|
||||
{
|
||||
static std::size_t fn( T v )
|
||||
{
|
||||
boost::uint64_t w[ 2 ];
|
||||
std::memcpy( &w, &v, sizeof( v ) );
|
||||
|
||||
std::size_t seed = 0;
|
||||
|
||||
seed ^= static_cast<std::size_t>( w[0] ) + ( seed << 6 ) + ( seed >> 2 );
|
||||
seed ^= static_cast<std::size_t>( w[1] ) + ( seed << 6 ) + ( seed >> 2 );
|
||||
|
||||
return seed;
|
||||
}
|
||||
};
|
||||
|
||||
template<class T, int Digits> struct hash_float_impl<T, 128, Digits, 32>
|
||||
{
|
||||
static std::size_t fn( T v )
|
||||
{
|
||||
boost::uint32_t w[ 4 ];
|
||||
std::memcpy( &w, &v, sizeof( v ) );
|
||||
|
||||
std::size_t seed = 0;
|
||||
|
||||
seed ^= static_cast<std::size_t>( w[0] ) + ( seed << 6 ) + ( seed >> 2 );
|
||||
seed ^= static_cast<std::size_t>( w[1] ) + ( seed << 6 ) + ( seed >> 2 );
|
||||
seed ^= static_cast<std::size_t>( w[2] ) + ( seed << 6 ) + ( seed >> 2 );
|
||||
seed ^= static_cast<std::size_t>( w[3] ) + ( seed << 6 ) + ( seed >> 2 );
|
||||
|
||||
return seed;
|
||||
}
|
||||
};
|
||||
|
||||
} // namespace hash_detail
|
||||
|
||||
template <typename T>
|
||||
typename boost::enable_if_<boost::is_floating_point<T>::value, std::size_t>::type
|
||||
hash_value( T v )
|
||||
{
|
||||
return boost::hash_detail::hash_float_impl<T>::fn( v + 0 );
|
||||
}
|
||||
|
||||
// pointer types
|
||||
|
||||
// `x + (x >> 3)` adjustment by Alberto Barbati and Dave Harris.
|
||||
template <class T> std::size_t hash_value( T* const& v )
|
||||
{
|
||||
boost::uintptr_t x = reinterpret_cast<boost::uintptr_t>( v );
|
||||
return boost::hash_value( x + (x >> 3) );
|
||||
}
|
||||
|
||||
// array types
|
||||
|
||||
template<class T, std::size_t N>
|
||||
inline std::size_t hash_value( T const (&x)[ N ] )
|
||||
{
|
||||
return boost::hash_range( x, x + N );
|
||||
}
|
||||
|
||||
template<class T, std::size_t N>
|
||||
inline std::size_t hash_value( T (&x)[ N ] )
|
||||
{
|
||||
return boost::hash_range( x, x + N );
|
||||
}
|
||||
|
||||
// complex
|
||||
|
||||
template <class T>
|
||||
std::size_t hash_value( std::complex<T> const& v )
|
||||
{
|
||||
std::size_t re = boost::hash<T>()( v.real() );
|
||||
std::size_t im = boost::hash<T>()( v.imag() );
|
||||
|
||||
im ^= re + ( im << 6 ) + ( im >> 2 );
|
||||
return im;
|
||||
}
|
||||
|
||||
// pair
|
||||
|
||||
template <class A, class B>
|
||||
std::size_t hash_value( std::pair<A, B> const& v )
|
||||
{
|
||||
std::size_t seed = 0;
|
||||
|
||||
boost::hash_combine( seed, v.first );
|
||||
boost::hash_combine( seed, v.second );
|
||||
|
||||
return seed;
|
||||
}
|
||||
|
||||
// ranges (list, set, deque...)
|
||||
|
||||
template <typename T>
|
||||
typename boost::enable_if_<hash_detail::is_range<T>::value && !hash_detail::is_contiguous_range<T>::value && !hash_detail::is_unordered_range<T>::value, std::size_t>::type
|
||||
hash_value( T const& v )
|
||||
{
|
||||
return boost::hash_range( v.begin(), v.end() );
|
||||
}
|
||||
|
||||
// contiguous ranges (string, vector, array)
|
||||
|
||||
template <typename T>
|
||||
typename boost::enable_if_<hash_detail::is_contiguous_range<T>::value, std::size_t>::type
|
||||
hash_value( T const& v )
|
||||
{
|
||||
return boost::hash_range( v.data(), v.data() + v.size() );
|
||||
}
|
||||
|
||||
// unordered ranges (unordered_set, unordered_map)
|
||||
|
||||
template <typename T>
|
||||
typename boost::enable_if_<hash_detail::is_unordered_range<T>::value, std::size_t>::type
|
||||
hash_value( T const& v )
|
||||
{
|
||||
return boost::hash_unordered_range( v.begin(), v.end() );
|
||||
}
|
||||
|
||||
#if defined(BOOST_MSVC) && BOOST_MSVC >= 1910 && BOOST_MSVC < 1920 && BOOST_CXX_VERSION >= 201700L
|
||||
|
||||
// resolve ambiguity with unconstrained stdext::hash_value in <xhash> :-/
|
||||
|
||||
template<template<class...> class L, class... T>
|
||||
typename boost::enable_if_<hash_detail::is_range<L<T...>>::value && !hash_detail::is_contiguous_range<L<T...>>::value && !hash_detail::is_unordered_range<L<T...>>::value, std::size_t>::type
|
||||
hash_value( L<T...> const& v )
|
||||
{
|
||||
return boost::hash_range( v.begin(), v.end() );
|
||||
}
|
||||
|
||||
// contiguous ranges (string, vector, array)
|
||||
|
||||
template<template<class...> class L, class... T>
|
||||
typename boost::enable_if_<hash_detail::is_contiguous_range<L<T...>>::value, std::size_t>::type
|
||||
hash_value( L<T...> const& v )
|
||||
{
|
||||
return boost::hash_range( v.data(), v.data() + v.size() );
|
||||
}
|
||||
|
||||
template<template<class, std::size_t> class L, class T, std::size_t N>
|
||||
typename boost::enable_if_<hash_detail::is_contiguous_range<L<T, N>>::value, std::size_t>::type
|
||||
hash_value( L<T, N> const& v )
|
||||
{
|
||||
return boost::hash_range( v.data(), v.data() + v.size() );
|
||||
}
|
||||
|
||||
// unordered ranges (unordered_set, unordered_map)
|
||||
|
||||
template<template<class...> class L, class... T>
|
||||
typename boost::enable_if_<hash_detail::is_unordered_range<L<T...>>::value, std::size_t>::type
|
||||
hash_value( L<T...> const& v )
|
||||
{
|
||||
return boost::hash_unordered_range( v.begin(), v.end() );
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
// std::unique_ptr, std::shared_ptr
|
||||
|
||||
#if !defined(BOOST_NO_CXX11_SMART_PTR)
|
||||
|
||||
template <typename T>
|
||||
std::size_t hash_value( std::shared_ptr<T> const& x )
|
||||
{
|
||||
return boost::hash_value( x.get() );
|
||||
}
|
||||
|
||||
template <typename T, typename Deleter>
|
||||
std::size_t hash_value( std::unique_ptr<T, Deleter> const& x )
|
||||
{
|
||||
return boost::hash_value( x.get() );
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
// std::type_index
|
||||
|
||||
#if !defined(BOOST_NO_CXX11_HDR_TYPEINDEX)
|
||||
|
||||
inline std::size_t hash_value( std::type_index const& v )
|
||||
{
|
||||
return v.hash_code();
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
// std::error_code, std::error_condition
|
||||
|
||||
#if !defined(BOOST_NO_CXX11_HDR_SYSTEM_ERROR)
|
||||
|
||||
inline std::size_t hash_value( std::error_code const& v )
|
||||
{
|
||||
std::size_t seed = 0;
|
||||
|
||||
boost::hash_combine( seed, v.value() );
|
||||
boost::hash_combine( seed, &v.category() );
|
||||
|
||||
return seed;
|
||||
}
|
||||
|
||||
inline std::size_t hash_value( std::error_condition const& v )
|
||||
{
|
||||
std::size_t seed = 0;
|
||||
|
||||
boost::hash_combine( seed, v.value() );
|
||||
boost::hash_combine( seed, &v.category() );
|
||||
|
||||
return seed;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
// std::optional
|
||||
|
||||
#if !defined(BOOST_NO_CXX17_HDR_OPTIONAL)
|
||||
|
||||
template <typename T>
|
||||
std::size_t hash_value( std::optional<T> const& v )
|
||||
{
|
||||
if( !v )
|
||||
{
|
||||
// Arbitray value for empty optional.
|
||||
return 0x12345678;
|
||||
}
|
||||
else
|
||||
{
|
||||
return boost::hash<T>()(*v);
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
// std::variant
|
||||
|
||||
#if !defined(BOOST_NO_CXX17_HDR_VARIANT)
|
||||
|
||||
inline std::size_t hash_value( std::monostate )
|
||||
{
|
||||
return 0x87654321;
|
||||
}
|
||||
|
||||
template <typename... Types>
|
||||
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
|
||||
|
||||
//
|
||||
// boost::hash_combine
|
||||
//
|
||||
|
||||
namespace hash_detail
|
||||
{
|
||||
|
||||
template<std::size_t Bits> struct hash_combine_impl
|
||||
{
|
||||
template <typename SizeT>
|
||||
inline static SizeT fn(SizeT seed, SizeT value)
|
||||
{
|
||||
seed ^= value + 0x9e3779b9 + (seed<<6) + (seed>>2);
|
||||
return seed;
|
||||
}
|
||||
};
|
||||
|
||||
template<> struct hash_combine_impl<32>
|
||||
{
|
||||
inline static boost::uint32_t fn(boost::uint32_t h1, boost::uint32_t k1)
|
||||
{
|
||||
const boost::uint32_t c1 = 0xcc9e2d51;
|
||||
const boost::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;
|
||||
|
||||
return h1;
|
||||
}
|
||||
};
|
||||
|
||||
template<> struct hash_combine_impl<64>
|
||||
{
|
||||
inline static boost::uint64_t fn(boost::uint64_t h, boost::uint64_t k)
|
||||
{
|
||||
const boost::uint64_t m = (boost::uint64_t(0xc6a4a793) << 32) + 0x5bd1e995;
|
||||
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;
|
||||
|
||||
return h;
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
#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;
|
||||
seed = boost::hash_detail::hash_combine_impl<sizeof(std::size_t) * CHAR_BIT>::fn(seed, hasher(v));
|
||||
}
|
||||
|
||||
#if defined(BOOST_MSVC)
|
||||
#pragma warning(pop)
|
||||
#endif
|
||||
|
||||
//
|
||||
// boost::hash_range
|
||||
//
|
||||
|
||||
template <class It>
|
||||
inline std::size_t hash_range(It first, It last)
|
||||
{
|
||||
std::size_t seed = 0;
|
||||
|
||||
hash_range(seed, first, last);
|
||||
|
||||
return seed;
|
||||
}
|
||||
|
||||
template <class It>
|
||||
inline void hash_range(std::size_t& seed, It first, It last)
|
||||
{
|
||||
for(; first != last; ++first)
|
||||
{
|
||||
hash_combine<typename std::iterator_traits<It>::value_type>(seed, *first);
|
||||
}
|
||||
}
|
||||
|
||||
//
|
||||
// boost::hash
|
||||
//
|
||||
|
||||
template <class T> struct hash
|
||||
{
|
||||
typedef T argument_type;
|
||||
typedef std::size_t result_type;
|
||||
|
||||
std::size_t operator()( T const& val ) const
|
||||
{
|
||||
return hash_value( val );
|
||||
}
|
||||
};
|
||||
|
||||
#if defined(BOOST_MSVC) && BOOST_MSVC >= 1910 && BOOST_MSVC < 1920 && BOOST_CXX_VERSION >= 201700L
|
||||
|
||||
// msvc-14.1 has stdext::hash_value for basic_string in <xhash> :-/
|
||||
|
||||
template<class E, class T, class A> struct hash< std::basic_string<E, T, A> >
|
||||
{
|
||||
typedef std::basic_string<E, T, A> argument_type;
|
||||
typedef std::size_t result_type;
|
||||
|
||||
std::size_t operator()( std::basic_string<E, T, A> const& val ) const
|
||||
{
|
||||
return boost::hash_value( val );
|
||||
}
|
||||
};
|
||||
|
||||
#endif
|
||||
}
|
||||
|
||||
#undef BOOST_FUNCTIONAL_HASH_ROTL32
|
||||
|
||||
#endif // #ifndef BOOST_FUNCTIONAL_HASH_HASH_HPP
|
24
include/boost/container_hash/hash_fwd.hpp
Normal file
24
include/boost/container_hash/hash_fwd.hpp
Normal file
@ -0,0 +1,24 @@
|
||||
// Copyright 2005-2009 Daniel James.
|
||||
// Copyright 2021 Peter Dimov.
|
||||
// Distributed under the Boost Software License, Version 1.0.
|
||||
// https://www.boost.org/LICENSE_1_0.txt
|
||||
|
||||
#ifndef BOOST_FUNCTIONAL_HASH_FWD_HPP
|
||||
#define BOOST_FUNCTIONAL_HASH_FWD_HPP
|
||||
|
||||
#include <cstddef>
|
||||
|
||||
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);
|
||||
|
||||
template <class It> std::size_t hash_unordered_range(It, It);
|
||||
template <class It> void hash_unordered_range(std::size_t&, It, It);
|
||||
}
|
||||
|
||||
#endif // #ifndef BOOST_FUNCTIONAL_HASH_FWD_HPP
|
6
include/boost/functional/hash.hpp
Normal file
6
include/boost/functional/hash.hpp
Normal file
@ -0,0 +1,6 @@
|
||||
|
||||
// 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)
|
||||
|
||||
#include <boost/container_hash/hash.hpp>
|
6
include/boost/functional/hash/extensions.hpp
Normal file
6
include/boost/functional/hash/extensions.hpp
Normal file
@ -0,0 +1,6 @@
|
||||
|
||||
// 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)
|
||||
|
||||
#include <boost/container_hash/extensions.hpp>
|
6
include/boost/functional/hash/hash.hpp
Normal file
6
include/boost/functional/hash/hash.hpp
Normal file
@ -0,0 +1,6 @@
|
||||
|
||||
// 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)
|
||||
|
||||
#include <boost/container_hash/hash.hpp>
|
6
include/boost/functional/hash/hash_fwd.hpp
Normal file
6
include/boost/functional/hash/hash_fwd.hpp
Normal file
@ -0,0 +1,6 @@
|
||||
|
||||
// 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)
|
||||
|
||||
#include <boost/container_hash/hash_fwd.hpp>
|
6
include/boost/functional/hash_fwd.hpp
Normal file
6
include/boost/functional/hash_fwd.hpp
Normal file
@ -0,0 +1,6 @@
|
||||
|
||||
// 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)
|
||||
|
||||
#include <boost/container_hash/hash_fwd.hpp>
|
16
index.html
Normal file
16
index.html
Normal file
@ -0,0 +1,16 @@
|
||||
|
||||
<!--
|
||||
Copyright 2005-2007 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)
|
||||
-->
|
||||
|
||||
<html>
|
||||
<head>
|
||||
<meta http-equiv="refresh" content="0; URL=doc/html/hash.html">
|
||||
</head>
|
||||
<body>
|
||||
Automatic redirection failed, please go to
|
||||
<a href="doc/html/hash.html">doc/html/hash.html</a>
|
||||
</body>
|
||||
</html>
|
96
meta/explicit-failures-markup.xml
Normal file
96
meta/explicit-failures-markup.xml
Normal file
@ -0,0 +1,96 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<!--
|
||||
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)
|
||||
-->
|
||||
<explicit-failures-markup>
|
||||
<!-- container_hash -->
|
||||
<library name="container_hash">
|
||||
<mark-expected-failures>
|
||||
<test name="hash_value_array_test"/>
|
||||
<toolset name="msvc-6.5*"/>
|
||||
<toolset name="msvc-7.0*"/>
|
||||
<note author="Daniel James">
|
||||
hash_value is not overloaded for arrays for older versions
|
||||
of Visual C++. There is a work around so that
|
||||
boost::hash<T[N]>, boost::hash_combine and boost::hash_range
|
||||
work.
|
||||
</note>
|
||||
</mark-expected-failures>
|
||||
|
||||
<mark-expected-failures>
|
||||
<test name="hash_function_pointer_test"/>
|
||||
<toolset name="msvc-6.5*"/>
|
||||
<toolset name="msvc-7.0*"/>
|
||||
<note refid="2" author="Daniel James"/>
|
||||
</mark-expected-failures>
|
||||
|
||||
<mark-expected-failures>
|
||||
<test name="hash_function_pointer_test"/>
|
||||
<toolset name="sun-5.7"/>
|
||||
<toolset name="sun-5.8"/>
|
||||
<toolset name="sun-5.9"/>
|
||||
<note author="Daniel James">
|
||||
On these compilers the wrong overload of hash_value is called
|
||||
when the argument is a hash function pointer. So calling
|
||||
hash_value doesn't work but boost::hash does work (and it's
|
||||
recommended that user never call hash_value directly so this
|
||||
shouldn't be a problem).
|
||||
</note>
|
||||
</mark-expected-failures>
|
||||
|
||||
<mark-expected-failures>
|
||||
<test name="hash_long_double_test"/>
|
||||
<toolset name="gcc-3.4.3_sunos"/>
|
||||
<toolset name="*pa_risc"/>
|
||||
<note author="Daniel James">
|
||||
This platform has poor support for <code>long double</code> so
|
||||
the hash function perform poorly for values out of the range
|
||||
of <code>double</code> or if they differ at a greater precision
|
||||
that <code>double</code> is capable of representing.
|
||||
</note>
|
||||
</mark-expected-failures>
|
||||
|
||||
<mark-expected-failures>
|
||||
<test name="point" />
|
||||
<test name="books" />
|
||||
<toolset name="msvc-6.5*"/>
|
||||
<toolset name="msvc-7.0*"/>
|
||||
<note author="Daniel James">
|
||||
These examples only work on compilers with support for ADL.
|
||||
It is possible to work around this, but I wanted to keep the
|
||||
example code as clean as possible.
|
||||
</note>
|
||||
</mark-expected-failures>
|
||||
|
||||
<mark-expected-failures>
|
||||
<test name="point" />
|
||||
<toolset name="borland-*"/>
|
||||
<note author="Daniel James">
|
||||
It appears that Borland doesn't find friend functions defined
|
||||
in a class by ADL. This is easily fixed but this example is
|
||||
meant to show the typical way of customising boost::hash, not
|
||||
the portable way.
|
||||
</note>
|
||||
</mark-expected-failures>
|
||||
|
||||
<mark-expected-failures>
|
||||
<test name="hash_global_namespace_test" />
|
||||
<toolset name="borland-*"/>
|
||||
<note author="Daniel James">
|
||||
The test demonstrates a Borland bug - functions that aren't
|
||||
in a namespace don't appear to be found by ADL.
|
||||
</note>
|
||||
</mark-expected-failures>
|
||||
|
||||
<mark-expected-failures>
|
||||
<test name="container_fwd_gcc_debug"/>
|
||||
<toolset name="darwin-4.2"/>
|
||||
<note author="Daniel James">
|
||||
Debug containers aren't supported on Apple's version of gcc 4.2.
|
||||
</note>
|
||||
</mark-expected-failures>
|
||||
</library>
|
||||
</explicit-failures-markup>
|
21
meta/libraries.json
Normal file
21
meta/libraries.json
Normal file
@ -0,0 +1,21 @@
|
||||
[
|
||||
{
|
||||
"key": "container_hash",
|
||||
"boost-version": "1.33.0",
|
||||
"name": "Container Hash",
|
||||
"authors": [
|
||||
"Daniel James"
|
||||
],
|
||||
"maintainers": [
|
||||
"Daniel James <dnljms -at- gmail.com>"
|
||||
],
|
||||
"description": "An STL-compatible hash function object that can be extended to hash user defined types.",
|
||||
"std": [
|
||||
"tr1"
|
||||
],
|
||||
"category": [
|
||||
"Function-objects"
|
||||
],
|
||||
"cxxstd": "03"
|
||||
}
|
||||
]
|
11
test/CMakeLists.txt
Normal file
11
test/CMakeLists.txt
Normal file
@ -0,0 +1,11 @@
|
||||
# Copyright 2018, 2019, 2021 Peter Dimov
|
||||
# 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(BoostTestJamfile OPTIONAL RESULT_VARIABLE HAVE_BOOST_TEST)
|
||||
|
||||
if(HAVE_BOOST_TEST)
|
||||
|
||||
boost_test_jamfile(FILE Jamfile.v2 LINK_LIBRARIES Boost::container_hash Boost::core Boost::utility)
|
||||
|
||||
endif()
|
83
test/Jamfile.v2
Normal file
83
test/Jamfile.v2
Normal file
@ -0,0 +1,83 @@
|
||||
# Copyright 2005-2012 Daniel James.
|
||||
# Copyright 2022 Peter Dimov
|
||||
# Distributed under the Boost Software License, Version 1.0.
|
||||
# https://www.boost.org/LICENSE_1_0.txt
|
||||
|
||||
import testing ;
|
||||
|
||||
local gcc-flags = -Wunused-parameter -Wconversion -Wsign-conversion -Wfloat-equal -Wshadow -Wno-variadic-macros ;
|
||||
local clang-flags = $(gcc-flags) -Wno-c99-extensions ;
|
||||
|
||||
project hash-tests
|
||||
: requirements
|
||||
<warnings>pedantic
|
||||
<toolset>intel:<warnings>on
|
||||
<toolset>gcc:<cxxflags>$(gcc-flags)
|
||||
<toolset>darwin:<cxxflags>$(gcc-flags)
|
||||
<toolset>clang:<cxxflags>$(clang-flags)
|
||||
<toolset>msvc:<warnings-as-errors>on
|
||||
<toolset>gcc:<warnings-as-errors>on
|
||||
<toolset>clang:<warnings-as-errors>on
|
||||
;
|
||||
|
||||
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 ;
|
||||
run hash_number_test.cpp ;
|
||||
run hash_enum_test.cpp ;
|
||||
run hash_pointer_test.cpp ;
|
||||
run hash_function_pointer_test.cpp ;
|
||||
run hash_float_test.cpp ;
|
||||
run hash_long_double_test.cpp ;
|
||||
run hash_string_test.cpp ;
|
||||
run hash_range_test.cpp ;
|
||||
run hash_custom_test.cpp ;
|
||||
run hash_global_namespace_test.cpp ;
|
||||
run hash_friend_test.cpp ;
|
||||
run hash_built_in_array_test.cpp ;
|
||||
run hash_value_array_test.cpp ;
|
||||
run hash_vector_test.cpp ;
|
||||
run hash_list_test.cpp ;
|
||||
run hash_deque_test.cpp ;
|
||||
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 ;
|
||||
run link_test.cpp link_test_2.cpp ;
|
||||
run link_ext_test.cpp link_no_ext_test.cpp ;
|
||||
run extensions_hpp_test.cpp ;
|
||||
compile-fail namespace_fail_test.cpp ;
|
||||
run implicit_test.cpp ;
|
||||
run hash_no_ext_macro_1.cpp ;
|
||||
run hash_no_ext_macro_2.cpp ;
|
||||
|
||||
build-project ../examples ;
|
||||
|
||||
run hash_reference_values.cpp ;
|
||||
|
||||
run detail_is_range_test.cpp ;
|
||||
run detail_is_contiguous_range_test.cpp ;
|
||||
run detail_is_unordered_range_test.cpp ;
|
||||
|
||||
run hash_forward_list_test.cpp ;
|
||||
|
||||
run quick.cpp ;
|
||||
|
||||
run hash_number_test2.cpp ;
|
||||
run hash_integral_test.cpp ;
|
||||
run hash_string_test2.cpp ;
|
||||
|
||||
# for gcc-4.8
|
||||
local fs-path-req = "-<toolset>gcc:<cxxflags>-Wshadow" "-<toolset>gcc:<cxxflags>-Wconversion" ;
|
||||
|
||||
run hash_fs_path_test.cpp /boost//filesystem/<warnings>off : : : $(fs-path-req) <toolset>msvc-14.0,<cxxstd>latest:<build>no ;
|
||||
run detail_is_range_test2.cpp : : : $(fs-path-req) ;
|
||||
|
||||
run hash_container_test.cpp ;
|
63
test/check_float_funcs.cpp
Normal file
63
test/check_float_funcs.cpp
Normal file
@ -0,0 +1,63 @@
|
||||
|
||||
// Copyright 2012 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)
|
||||
|
||||
#if defined(__GNUC__)
|
||||
// in type_traits/is_complete.hpp:47
|
||||
#pragma GCC diagnostic ignored "-Wconversion"
|
||||
#endif
|
||||
|
||||
#include <boost/static_assert.hpp>
|
||||
#include <boost/type_traits/is_same.hpp>
|
||||
#include <boost/type_traits/is_convertible.hpp>
|
||||
#include <cmath>
|
||||
|
||||
namespace test
|
||||
{
|
||||
template <class T1>
|
||||
struct check_return_type
|
||||
{
|
||||
template <class T2>
|
||||
static void equals(T2)
|
||||
{
|
||||
BOOST_STATIC_ASSERT((boost::is_same<T1, T2>::value));
|
||||
}
|
||||
|
||||
template <class T2>
|
||||
static void equals_ref(T2&)
|
||||
{
|
||||
BOOST_STATIC_ASSERT((boost::is_same<T1, T2>::value));
|
||||
}
|
||||
|
||||
template <class T2>
|
||||
static void convertible(T2)
|
||||
{
|
||||
BOOST_STATIC_ASSERT((boost::is_convertible<T2, T1>::value));
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
int main() {
|
||||
float f = 0;
|
||||
double d = 0;
|
||||
long double l = 0;
|
||||
|
||||
test::check_return_type<float>::equals(std::ldexp(f, 0));
|
||||
test::check_return_type<double>::equals(std::ldexp(d, 0));
|
||||
test::check_return_type<long double>::equals(std::ldexp(l, 0));
|
||||
|
||||
int dummy = 0;
|
||||
|
||||
test::check_return_type<float>::equals(std::frexp(f, &dummy));
|
||||
test::check_return_type<double>::equals(std::frexp(d, &dummy));
|
||||
test::check_return_type<long double>::equals(std::frexp(l, &dummy));
|
||||
|
||||
#if BOOST_HASH_USE_FPCLASSIFY
|
||||
|
||||
int (*fpc1)(float) = std::fpclassify;
|
||||
int (*fpc2)(double) = std::fpclassify;
|
||||
int (*fpc3)(long double) = std::fpclassify;
|
||||
|
||||
#endif
|
||||
}
|
17
test/cmake_install_test/CMakeLists.txt
Normal file
17
test/cmake_install_test/CMakeLists.txt
Normal file
@ -0,0 +1,17 @@
|
||||
# Copyright 2018, 2019, 2021 Peter Dimov
|
||||
# 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
|
||||
|
||||
cmake_minimum_required(VERSION 3.5...3.20)
|
||||
|
||||
project(cmake_install_test LANGUAGES CXX)
|
||||
|
||||
find_package(boost_container_hash REQUIRED)
|
||||
|
||||
add_executable(quick ../quick.cpp)
|
||||
target_link_libraries(quick Boost::container_hash)
|
||||
|
||||
enable_testing()
|
||||
add_test(quick quick)
|
||||
|
||||
add_custom_target(check COMMAND ${CMAKE_CTEST_COMMAND} --output-on-failure -C $<CONFIG>)
|
21
test/cmake_subdir_test/CMakeLists.txt
Normal file
21
test/cmake_subdir_test/CMakeLists.txt
Normal file
@ -0,0 +1,21 @@
|
||||
# Copyright 2018, 2019, 2021 Peter Dimov
|
||||
# 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
|
||||
|
||||
cmake_minimum_required(VERSION 3.5...3.20)
|
||||
|
||||
project(cmake_subdir_test LANGUAGES CXX)
|
||||
|
||||
add_subdirectory(../.. boostorg/container_hash)
|
||||
|
||||
add_subdirectory(../../../config boostorg/config)
|
||||
add_subdirectory(../../../type_traits boostorg/type_traits)
|
||||
add_subdirectory(../../../static_assert boostorg/static_assert)
|
||||
|
||||
add_executable(quick ../quick.cpp)
|
||||
target_link_libraries(quick Boost::container_hash)
|
||||
|
||||
enable_testing()
|
||||
add_test(quick quick)
|
||||
|
||||
add_custom_target(check COMMAND ${CMAKE_CTEST_COMMAND} --output-on-failure -C $<CONFIG>)
|
20
test/compile_time.hpp
Normal file
20
test/compile_time.hpp
Normal file
@ -0,0 +1,20 @@
|
||||
|
||||
// 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)
|
||||
|
||||
#include <boost/config.hpp>
|
||||
#include <boost/static_assert.hpp>
|
||||
#include <boost/type_traits/is_same.hpp>
|
||||
|
||||
template <class T>
|
||||
void compile_time_tests(T*)
|
||||
{
|
||||
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));
|
||||
}
|
||||
|
25
test/config.hpp
Normal file
25
test/config.hpp
Normal file
@ -0,0 +1,25 @@
|
||||
|
||||
// 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)
|
||||
|
||||
#if defined(BOOST_HASH_TEST_STD)
|
||||
# define BOOST_HASH_TEST_STD_INCLUDES
|
||||
# define BOOST_HASH_TEST_NAMESPACE std
|
||||
#else
|
||||
# define BOOST_HASH_TEST_NAMESPACE boost
|
||||
# if !defined(BOOST_HASH_NO_EXTENSIONS)
|
||||
# define BOOST_HASH_TEST_EXTENSIONS
|
||||
# endif
|
||||
#endif
|
||||
|
||||
#if defined(_WIN32_WCE)
|
||||
// The standard windows mobile headers trigger this warning so I disable it
|
||||
// before doing anything else.
|
||||
#pragma warning(disable:4201) // nonstandard extension used :
|
||||
// nameless struct/union
|
||||
|
||||
#endif
|
||||
|
||||
#define HASH_TEST_CAT(x, y) HASH_TEST_CAT2(x, y)
|
||||
#define HASH_TEST_CAT2(x, y) x##y
|
101
test/detail_is_contiguous_range_test.cpp
Normal file
101
test/detail_is_contiguous_range_test.cpp
Normal file
@ -0,0 +1,101 @@
|
||||
// Copyright 2017, 2018 Peter Dimov.
|
||||
// Distributed under the Boost Software License, Version 1.0.
|
||||
// https://www.boost.org/LICENSE_1_0.txt
|
||||
|
||||
#include <boost/container_hash/detail/is_contiguous_range.hpp>
|
||||
#include <boost/core/lightweight_test_trait.hpp>
|
||||
#include <boost/config.hpp>
|
||||
#include <string>
|
||||
#include <vector>
|
||||
#include <list>
|
||||
#include <deque>
|
||||
#include <set>
|
||||
#include <map>
|
||||
#if !defined(BOOST_NO_CXX11_HDR_ARRAY)
|
||||
# include <array>
|
||||
#endif
|
||||
#if !defined(BOOST_NO_CXX11_HDR_FORWARD_LIST)
|
||||
# include <forward_list>
|
||||
#endif
|
||||
#if !defined(BOOST_NO_CXX11_HDR_UNORDERED_SET)
|
||||
# include <unordered_set>
|
||||
#endif
|
||||
#if !defined(BOOST_NO_CXX11_HDR_UNORDERED_MAP)
|
||||
# include <unordered_map>
|
||||
#endif
|
||||
|
||||
struct X
|
||||
{
|
||||
};
|
||||
|
||||
int main()
|
||||
{
|
||||
using boost::hash_detail::is_contiguous_range;
|
||||
|
||||
BOOST_TEST_TRAIT_FALSE((is_contiguous_range<void>));
|
||||
BOOST_TEST_TRAIT_FALSE((is_contiguous_range<void const>));
|
||||
|
||||
BOOST_TEST_TRAIT_FALSE((is_contiguous_range<int>));
|
||||
BOOST_TEST_TRAIT_FALSE((is_contiguous_range<int const>));
|
||||
|
||||
BOOST_TEST_TRAIT_FALSE((is_contiguous_range<X>));
|
||||
BOOST_TEST_TRAIT_FALSE((is_contiguous_range<X const>));
|
||||
|
||||
BOOST_TEST_TRAIT_FALSE((is_contiguous_range<int[2]>));
|
||||
BOOST_TEST_TRAIT_FALSE((is_contiguous_range<int const[2]>));
|
||||
|
||||
BOOST_TEST_TRAIT_TRUE((is_contiguous_range<std::string>));
|
||||
BOOST_TEST_TRAIT_TRUE((is_contiguous_range<std::string const>));
|
||||
|
||||
BOOST_TEST_TRAIT_TRUE((is_contiguous_range<std::wstring>));
|
||||
BOOST_TEST_TRAIT_TRUE((is_contiguous_range<std::wstring const>));
|
||||
|
||||
// std::vector doesn't have data() in C++03
|
||||
#if !defined(BOOST_NO_CXX11_DECLTYPE) && !defined(BOOST_NO_SFINAE_EXPR) && !BOOST_WORKAROUND(BOOST_GCC, < 40700)
|
||||
BOOST_TEST_TRAIT_TRUE((is_contiguous_range< std::vector<X> >));
|
||||
BOOST_TEST_TRAIT_TRUE((is_contiguous_range< std::vector<X> const >));
|
||||
#endif
|
||||
|
||||
BOOST_TEST_TRAIT_FALSE((is_contiguous_range< std::deque<X> >));
|
||||
BOOST_TEST_TRAIT_FALSE((is_contiguous_range< std::deque<X> const >));
|
||||
|
||||
BOOST_TEST_TRAIT_FALSE((is_contiguous_range< std::set<int> >));
|
||||
BOOST_TEST_TRAIT_FALSE((is_contiguous_range< std::set<int> const >));
|
||||
|
||||
BOOST_TEST_TRAIT_FALSE((is_contiguous_range< std::multiset<int> >));
|
||||
BOOST_TEST_TRAIT_FALSE((is_contiguous_range< std::multiset<int> const >));
|
||||
|
||||
BOOST_TEST_TRAIT_FALSE((is_contiguous_range< std::map<int, X> >));
|
||||
BOOST_TEST_TRAIT_FALSE((is_contiguous_range< std::map<int, X> const >));
|
||||
|
||||
BOOST_TEST_TRAIT_FALSE((is_contiguous_range< std::multimap<int, X> >));
|
||||
BOOST_TEST_TRAIT_FALSE((is_contiguous_range< std::multimap<int, X> const >));
|
||||
|
||||
#if !defined(BOOST_NO_CXX11_HDR_ARRAY)
|
||||
BOOST_TEST_TRAIT_TRUE((is_contiguous_range< std::array<X, 2> >));
|
||||
BOOST_TEST_TRAIT_TRUE((is_contiguous_range< std::array<X, 2> const >));
|
||||
#endif
|
||||
|
||||
#if !defined(BOOST_NO_CXX11_HDR_FORWARD_LIST)
|
||||
BOOST_TEST_TRAIT_FALSE((is_contiguous_range< std::forward_list<X> >));
|
||||
BOOST_TEST_TRAIT_FALSE((is_contiguous_range< std::forward_list<X> const >));
|
||||
#endif
|
||||
|
||||
#if !defined(BOOST_NO_CXX11_HDR_UNORDERED_SET)
|
||||
BOOST_TEST_TRAIT_FALSE((is_contiguous_range< std::unordered_set<int> >));
|
||||
BOOST_TEST_TRAIT_FALSE((is_contiguous_range< std::unordered_set<int> const >));
|
||||
|
||||
BOOST_TEST_TRAIT_FALSE((is_contiguous_range< std::unordered_multiset<int> >));
|
||||
BOOST_TEST_TRAIT_FALSE((is_contiguous_range< std::unordered_multiset<int> const >));
|
||||
#endif
|
||||
|
||||
#if !defined(BOOST_NO_CXX11_HDR_UNORDERED_MAP)
|
||||
BOOST_TEST_TRAIT_FALSE((is_contiguous_range< std::unordered_map<int, X> >));
|
||||
BOOST_TEST_TRAIT_FALSE((is_contiguous_range< std::unordered_map<int, X> const >));
|
||||
|
||||
BOOST_TEST_TRAIT_FALSE((is_contiguous_range< std::unordered_multimap<int, X> >));
|
||||
BOOST_TEST_TRAIT_FALSE((is_contiguous_range< std::unordered_multimap<int, X> const >));
|
||||
#endif
|
||||
|
||||
return boost::report_errors();
|
||||
}
|
98
test/detail_is_range_test.cpp
Normal file
98
test/detail_is_range_test.cpp
Normal file
@ -0,0 +1,98 @@
|
||||
// Copyright 2017 Peter Dimov.
|
||||
// Distributed under the Boost Software License, Version 1.0.
|
||||
// https://www.boost.org/LICENSE_1_0.txt
|
||||
|
||||
#include <boost/container_hash/detail/is_range.hpp>
|
||||
#include <boost/core/lightweight_test_trait.hpp>
|
||||
#include <boost/config.hpp>
|
||||
#include <string>
|
||||
#include <vector>
|
||||
#include <list>
|
||||
#include <deque>
|
||||
#include <set>
|
||||
#include <map>
|
||||
#if !defined(BOOST_NO_CXX11_HDR_ARRAY)
|
||||
# include <array>
|
||||
#endif
|
||||
#if !defined(BOOST_NO_CXX11_HDR_FORWARD_LIST)
|
||||
# include <forward_list>
|
||||
#endif
|
||||
#if !defined(BOOST_NO_CXX11_HDR_UNORDERED_SET)
|
||||
# include <unordered_set>
|
||||
#endif
|
||||
#if !defined(BOOST_NO_CXX11_HDR_UNORDERED_MAP)
|
||||
# include <unordered_map>
|
||||
#endif
|
||||
|
||||
struct X
|
||||
{
|
||||
};
|
||||
|
||||
int main()
|
||||
{
|
||||
using boost::hash_detail::is_range;
|
||||
|
||||
BOOST_TEST_TRAIT_FALSE((is_range<void>));
|
||||
BOOST_TEST_TRAIT_FALSE((is_range<void const>));
|
||||
|
||||
BOOST_TEST_TRAIT_FALSE((is_range<int>));
|
||||
BOOST_TEST_TRAIT_FALSE((is_range<int const>));
|
||||
|
||||
BOOST_TEST_TRAIT_FALSE((is_range<X>));
|
||||
BOOST_TEST_TRAIT_FALSE((is_range<X const>));
|
||||
|
||||
BOOST_TEST_TRAIT_FALSE((is_range<int[2]>));
|
||||
BOOST_TEST_TRAIT_FALSE((is_range<int const[2]>));
|
||||
|
||||
BOOST_TEST_TRAIT_TRUE((is_range<std::string>));
|
||||
BOOST_TEST_TRAIT_TRUE((is_range<std::string const>));
|
||||
|
||||
BOOST_TEST_TRAIT_TRUE((is_range<std::wstring>));
|
||||
BOOST_TEST_TRAIT_TRUE((is_range<std::wstring const>));
|
||||
|
||||
BOOST_TEST_TRAIT_TRUE((is_range< std::vector<X> >));
|
||||
BOOST_TEST_TRAIT_TRUE((is_range< std::vector<X> const >));
|
||||
|
||||
BOOST_TEST_TRAIT_TRUE((is_range< std::deque<X> >));
|
||||
BOOST_TEST_TRAIT_TRUE((is_range< std::deque<X> const >));
|
||||
|
||||
BOOST_TEST_TRAIT_TRUE((is_range< std::set<int> >));
|
||||
BOOST_TEST_TRAIT_TRUE((is_range< std::set<int> const >));
|
||||
|
||||
BOOST_TEST_TRAIT_TRUE((is_range< std::multiset<int> >));
|
||||
BOOST_TEST_TRAIT_TRUE((is_range< std::multiset<int> const >));
|
||||
|
||||
BOOST_TEST_TRAIT_TRUE((is_range< std::map<int, X> >));
|
||||
BOOST_TEST_TRAIT_TRUE((is_range< std::map<int, X> const >));
|
||||
|
||||
BOOST_TEST_TRAIT_TRUE((is_range< std::multimap<int, X> >));
|
||||
BOOST_TEST_TRAIT_TRUE((is_range< std::multimap<int, X> const >));
|
||||
|
||||
#if !defined(BOOST_NO_CXX11_HDR_ARRAY)
|
||||
BOOST_TEST_TRAIT_TRUE((is_range< std::array<X, 2> >));
|
||||
BOOST_TEST_TRAIT_TRUE((is_range< std::array<X, 2> const >));
|
||||
#endif
|
||||
|
||||
#if !defined(BOOST_NO_CXX11_HDR_FORWARD_LIST)
|
||||
BOOST_TEST_TRAIT_TRUE((is_range< std::forward_list<X> >));
|
||||
BOOST_TEST_TRAIT_TRUE((is_range< std::forward_list<X> const >));
|
||||
#endif
|
||||
|
||||
#if !defined(BOOST_NO_CXX11_HDR_UNORDERED_SET)
|
||||
BOOST_TEST_TRAIT_TRUE((is_range< std::unordered_set<int> >));
|
||||
BOOST_TEST_TRAIT_TRUE((is_range< std::unordered_set<int> const >));
|
||||
|
||||
BOOST_TEST_TRAIT_TRUE((is_range< std::unordered_multiset<int> >));
|
||||
BOOST_TEST_TRAIT_TRUE((is_range< std::unordered_multiset<int> const >));
|
||||
#endif
|
||||
|
||||
#if !defined(BOOST_NO_CXX11_HDR_UNORDERED_MAP)
|
||||
BOOST_TEST_TRAIT_TRUE((is_range< std::unordered_map<int, X> >));
|
||||
BOOST_TEST_TRAIT_TRUE((is_range< std::unordered_map<int, X> const >));
|
||||
|
||||
BOOST_TEST_TRAIT_TRUE((is_range< std::unordered_multimap<int, X> >));
|
||||
BOOST_TEST_TRAIT_TRUE((is_range< std::unordered_multimap<int, X> const >));
|
||||
#endif
|
||||
|
||||
return boost::report_errors();
|
||||
}
|
37
test/detail_is_range_test2.cpp
Normal file
37
test/detail_is_range_test2.cpp
Normal file
@ -0,0 +1,37 @@
|
||||
// Copyright 2022 Peter Dimov
|
||||
// Distributed under the Boost Software License, Version 1.0.
|
||||
// https://www.boost.org/LICENSE_1_0.txt
|
||||
|
||||
#if defined(_MSC_VER)
|
||||
# pragma warning(disable: 4714) // forceinline not inlined
|
||||
#endif
|
||||
|
||||
#if defined(__GNUC__) || defined(__clang__)
|
||||
# pragma GCC diagnostic ignored "-Wsign-conversion"
|
||||
#endif
|
||||
|
||||
#include <boost/container_hash/detail/is_range.hpp>
|
||||
#include <boost/core/lightweight_test_trait.hpp>
|
||||
#include <boost/config.hpp>
|
||||
#include <boost/filesystem/path.hpp>
|
||||
|
||||
#if !defined(BOOST_NO_CXX17_HDR_FILESYSTEM) && !defined(__MINGW32__)
|
||||
# include <filesystem>
|
||||
#endif
|
||||
|
||||
int main()
|
||||
{
|
||||
using boost::hash_detail::is_range;
|
||||
|
||||
BOOST_TEST_TRAIT_FALSE((is_range< boost::filesystem::path >));
|
||||
BOOST_TEST_TRAIT_FALSE((is_range< boost::filesystem::path const >));
|
||||
|
||||
#if !defined(BOOST_NO_CXX17_HDR_FILESYSTEM) && !defined(__MINGW32__)
|
||||
|
||||
BOOST_TEST_TRAIT_FALSE((is_range< std::filesystem::path >));
|
||||
BOOST_TEST_TRAIT_FALSE((is_range< std::filesystem::path const >));
|
||||
|
||||
#endif
|
||||
|
||||
return boost::report_errors();
|
||||
}
|
98
test/detail_is_unordered_range_test.cpp
Normal file
98
test/detail_is_unordered_range_test.cpp
Normal file
@ -0,0 +1,98 @@
|
||||
// Copyright 2017 Peter Dimov.
|
||||
// Distributed under the Boost Software License, Version 1.0.
|
||||
// https://www.boost.org/LICENSE_1_0.txt
|
||||
|
||||
#include <boost/container_hash/detail/is_unordered_range.hpp>
|
||||
#include <boost/core/lightweight_test_trait.hpp>
|
||||
#include <boost/config.hpp>
|
||||
#include <string>
|
||||
#include <vector>
|
||||
#include <list>
|
||||
#include <deque>
|
||||
#include <set>
|
||||
#include <map>
|
||||
#if !defined(BOOST_NO_CXX11_HDR_ARRAY)
|
||||
# include <array>
|
||||
#endif
|
||||
#if !defined(BOOST_NO_CXX11_HDR_FORWARD_LIST)
|
||||
# include <forward_list>
|
||||
#endif
|
||||
#if !defined(BOOST_NO_CXX11_HDR_UNORDERED_SET)
|
||||
# include <unordered_set>
|
||||
#endif
|
||||
#if !defined(BOOST_NO_CXX11_HDR_UNORDERED_MAP)
|
||||
# include <unordered_map>
|
||||
#endif
|
||||
|
||||
struct X
|
||||
{
|
||||
};
|
||||
|
||||
int main()
|
||||
{
|
||||
using boost::hash_detail::is_unordered_range;
|
||||
|
||||
BOOST_TEST_TRAIT_FALSE((is_unordered_range<void>));
|
||||
BOOST_TEST_TRAIT_FALSE((is_unordered_range<void const>));
|
||||
|
||||
BOOST_TEST_TRAIT_FALSE((is_unordered_range<int>));
|
||||
BOOST_TEST_TRAIT_FALSE((is_unordered_range<int const>));
|
||||
|
||||
BOOST_TEST_TRAIT_FALSE((is_unordered_range<X>));
|
||||
BOOST_TEST_TRAIT_FALSE((is_unordered_range<X const>));
|
||||
|
||||
BOOST_TEST_TRAIT_FALSE((is_unordered_range<int[2]>));
|
||||
BOOST_TEST_TRAIT_FALSE((is_unordered_range<int const[2]>));
|
||||
|
||||
BOOST_TEST_TRAIT_FALSE((is_unordered_range<std::string>));
|
||||
BOOST_TEST_TRAIT_FALSE((is_unordered_range<std::string const>));
|
||||
|
||||
BOOST_TEST_TRAIT_FALSE((is_unordered_range<std::wstring>));
|
||||
BOOST_TEST_TRAIT_FALSE((is_unordered_range<std::wstring const>));
|
||||
|
||||
BOOST_TEST_TRAIT_FALSE((is_unordered_range< std::vector<X> >));
|
||||
BOOST_TEST_TRAIT_FALSE((is_unordered_range< std::vector<X> const >));
|
||||
|
||||
BOOST_TEST_TRAIT_FALSE((is_unordered_range< std::deque<X> >));
|
||||
BOOST_TEST_TRAIT_FALSE((is_unordered_range< std::deque<X> const >));
|
||||
|
||||
BOOST_TEST_TRAIT_FALSE((is_unordered_range< std::set<int> >));
|
||||
BOOST_TEST_TRAIT_FALSE((is_unordered_range< std::set<int> const >));
|
||||
|
||||
BOOST_TEST_TRAIT_FALSE((is_unordered_range< std::multiset<int> >));
|
||||
BOOST_TEST_TRAIT_FALSE((is_unordered_range< std::multiset<int> const >));
|
||||
|
||||
BOOST_TEST_TRAIT_FALSE((is_unordered_range< std::map<int, X> >));
|
||||
BOOST_TEST_TRAIT_FALSE((is_unordered_range< std::map<int, X> const >));
|
||||
|
||||
BOOST_TEST_TRAIT_FALSE((is_unordered_range< std::multimap<int, X> >));
|
||||
BOOST_TEST_TRAIT_FALSE((is_unordered_range< std::multimap<int, X> const >));
|
||||
|
||||
#if !defined(BOOST_NO_CXX11_HDR_ARRAY)
|
||||
BOOST_TEST_TRAIT_FALSE((is_unordered_range< std::array<X, 2> >));
|
||||
BOOST_TEST_TRAIT_FALSE((is_unordered_range< std::array<X, 2> const >));
|
||||
#endif
|
||||
|
||||
#if !defined(BOOST_NO_CXX11_HDR_FORWARD_LIST)
|
||||
BOOST_TEST_TRAIT_FALSE((is_unordered_range< std::forward_list<X> >));
|
||||
BOOST_TEST_TRAIT_FALSE((is_unordered_range< std::forward_list<X> const >));
|
||||
#endif
|
||||
|
||||
#if !defined(BOOST_NO_CXX11_HDR_UNORDERED_SET)
|
||||
BOOST_TEST_TRAIT_TRUE((is_unordered_range< std::unordered_set<int> >));
|
||||
BOOST_TEST_TRAIT_TRUE((is_unordered_range< std::unordered_set<int> const >));
|
||||
|
||||
BOOST_TEST_TRAIT_TRUE((is_unordered_range< std::unordered_multiset<int> >));
|
||||
BOOST_TEST_TRAIT_TRUE((is_unordered_range< std::unordered_multiset<int> const >));
|
||||
#endif
|
||||
|
||||
#if !defined(BOOST_NO_CXX11_HDR_UNORDERED_MAP)
|
||||
BOOST_TEST_TRAIT_TRUE((is_unordered_range< std::unordered_map<int, X> >));
|
||||
BOOST_TEST_TRAIT_TRUE((is_unordered_range< std::unordered_map<int, X> const >));
|
||||
|
||||
BOOST_TEST_TRAIT_TRUE((is_unordered_range< std::unordered_multimap<int, X> >));
|
||||
BOOST_TEST_TRAIT_TRUE((is_unordered_range< std::unordered_multimap<int, X> const >));
|
||||
#endif
|
||||
|
||||
return boost::report_errors();
|
||||
}
|
19
test/extensions_hpp_test.cpp
Normal file
19
test/extensions_hpp_test.cpp
Normal file
@ -0,0 +1,19 @@
|
||||
|
||||
// Copyright 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)
|
||||
|
||||
// Check that boost/container_hash/extensions.hpp works okay.
|
||||
//
|
||||
// It probably should be in boost/container_hash/detail, but since it isn't it
|
||||
// should work.
|
||||
|
||||
#include "./config.hpp"
|
||||
|
||||
#include <boost/container_hash/extensions.hpp>
|
||||
|
||||
int main() {
|
||||
int x[2] = { 2, 3 };
|
||||
boost::hash<int[2]> hf;
|
||||
hf(x);
|
||||
}
|
75
test/hash_built_in_array_test.cpp
Normal file
75
test/hash_built_in_array_test.cpp
Normal file
@ -0,0 +1,75 @@
|
||||
|
||||
// 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)
|
||||
|
||||
#include "./config.hpp"
|
||||
|
||||
#ifdef BOOST_HASH_TEST_EXTENSIONS
|
||||
# ifdef BOOST_HASH_TEST_STD_INCLUDES
|
||||
# include <functional>
|
||||
# else
|
||||
# include <boost/container_hash/hash.hpp>
|
||||
# endif
|
||||
#endif
|
||||
|
||||
#include <boost/core/lightweight_test.hpp>
|
||||
|
||||
#ifdef BOOST_HASH_TEST_EXTENSIONS
|
||||
|
||||
void array_int_test()
|
||||
{
|
||||
const int length1 = 25;
|
||||
int array1[25] = {
|
||||
26, -43, 32, 65, 45,
|
||||
12, 67, 32, 12, 23,
|
||||
0, 0, 0, 0, 0,
|
||||
8, -12, 23, 65, 45,
|
||||
-1, 93, -54, 987, 3
|
||||
};
|
||||
BOOST_HASH_TEST_NAMESPACE::hash<int[25]> hasher1;
|
||||
|
||||
const int length2 = 1;
|
||||
int array2[1] = {3};
|
||||
BOOST_HASH_TEST_NAMESPACE::hash<int[1]> hasher2;
|
||||
|
||||
const int length3 = 2;
|
||||
int array3[2] = {2, 3};
|
||||
BOOST_HASH_TEST_NAMESPACE::hash<int[2]> hasher3;
|
||||
|
||||
BOOST_TEST(hasher1(array1)
|
||||
== BOOST_HASH_TEST_NAMESPACE::hash_range(array1, array1 + length1));
|
||||
BOOST_TEST(hasher2(array2)
|
||||
== BOOST_HASH_TEST_NAMESPACE::hash_range(array2, array2 + length2));
|
||||
BOOST_TEST(hasher3(array3)
|
||||
== BOOST_HASH_TEST_NAMESPACE::hash_range(array3, array3 + length3));
|
||||
}
|
||||
|
||||
void two_dimensional_array_test()
|
||||
{
|
||||
int array[3][2] = {{-5, 6}, {7, -3}, {26, 1}};
|
||||
BOOST_HASH_TEST_NAMESPACE::hash<int[3][2]> hasher;
|
||||
|
||||
std::size_t seed1 = 0;
|
||||
for(int i = 0; i < 3; ++i)
|
||||
{
|
||||
std::size_t seed2 = 0;
|
||||
for(int j = 0; j < 2; ++j)
|
||||
BOOST_HASH_TEST_NAMESPACE::hash_combine(seed2, array[i][j]);
|
||||
BOOST_HASH_TEST_NAMESPACE::hash_combine(seed1, seed2);
|
||||
}
|
||||
|
||||
BOOST_TEST(hasher(array) == seed1);
|
||||
BOOST_TEST(hasher(array) == BOOST_HASH_TEST_NAMESPACE::hash_range(array, array + 3));
|
||||
}
|
||||
|
||||
#endif // BOOST_HASH_TEST_EXTENSIONS
|
||||
|
||||
int main()
|
||||
{
|
||||
#ifdef BOOST_HASH_TEST_EXTENSIONS
|
||||
array_int_test();
|
||||
two_dimensional_array_test();
|
||||
#endif
|
||||
return boost::report_errors();
|
||||
}
|
132
test/hash_complex_test.cpp
Normal file
132
test/hash_complex_test.cpp
Normal file
@ -0,0 +1,132 @@
|
||||
|
||||
// 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)
|
||||
|
||||
#include "./config.hpp"
|
||||
|
||||
#if !defined(BOOST_HASH_TEST_EXTENSIONS)
|
||||
|
||||
int main() {}
|
||||
|
||||
#else
|
||||
|
||||
#ifdef BOOST_HASH_TEST_STD_INCLUDES
|
||||
# include <functional>
|
||||
#else
|
||||
# include <boost/container_hash/hash.hpp>
|
||||
#endif
|
||||
|
||||
#include <boost/core/lightweight_test.hpp>
|
||||
|
||||
#if defined(BOOST_MSVC)
|
||||
#pragma warning(disable:4244) // conversion from 'unsigned long' to
|
||||
// 'unsigned short', possible loss of data
|
||||
#pragma warning(disable:4245) // conversion from 'int' to
|
||||
// 'const unsigned short',
|
||||
// signed/unsigned mismatch
|
||||
#pragma warning(disable:4305) // truncation from 'double' to
|
||||
// 'const std::complex<float>::_Ty'
|
||||
#pragma warning(disable:4309) // truncation of constant value
|
||||
#pragma warning(disable:4512) // assignment operator could not be generated
|
||||
#pragma warning(disable:4996) // std::complex<Integer> is deprecated
|
||||
#if BOOST_MSVC < 1400
|
||||
#pragma warning(disable:4267) // conversion from 'size_t' to 'unsigned int',
|
||||
// possible loss of data
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#if ( defined(__GNUC__) || defined(__clang__) ) && !defined(BOOST_INTEL_CXX_VERSION)
|
||||
#pragma GCC diagnostic ignored "-Wfloat-equal"
|
||||
#endif
|
||||
|
||||
#include <boost/limits.hpp>
|
||||
#include <complex>
|
||||
#include <sstream>
|
||||
#include <set>
|
||||
|
||||
template <class T>
|
||||
void generic_complex_tests(std::complex<T> v)
|
||||
{
|
||||
BOOST_HASH_TEST_NAMESPACE::hash<std::complex<T> > complex_hasher;
|
||||
|
||||
BOOST_TEST(complex_hasher(v) == complex_hasher(v));
|
||||
|
||||
BOOST_HASH_TEST_NAMESPACE::hash<T> real_hasher;
|
||||
T real = v.real();
|
||||
T imag = v.imag();
|
||||
|
||||
BOOST_TEST(real_hasher(real) == complex_hasher(std::complex<T>(real)));
|
||||
|
||||
if(imag != 0 && real_hasher(real) == complex_hasher(v)) {
|
||||
std::ostringstream os;
|
||||
os<<"real_hasher("<<real<<") == complex_hasher("
|
||||
<<v.real()<<" + "<<v.imag()<<"i) == "
|
||||
<<real_hasher(real)<<" (This might not be a bug).";
|
||||
BOOST_ERROR(os.str().c_str());
|
||||
}
|
||||
}
|
||||
|
||||
template <class Float>
|
||||
void complex_float_tests(Float*)
|
||||
{
|
||||
typedef std::complex<Float> complex;
|
||||
generic_complex_tests(complex(0,0));
|
||||
generic_complex_tests(complex(0.5,0));
|
||||
generic_complex_tests(complex(25,0));
|
||||
generic_complex_tests(complex(25,0));
|
||||
generic_complex_tests(complex(static_cast<Float>(-67.5324535),static_cast<Float>(56.23578678)));
|
||||
}
|
||||
|
||||
template <class Integer>
|
||||
void complex_integral_tests(Integer*)
|
||||
{
|
||||
typedef std::complex<Integer> complex;
|
||||
generic_complex_tests(complex(0,0));
|
||||
generic_complex_tests(complex(15342,124));
|
||||
generic_complex_tests(complex(25,54356));
|
||||
generic_complex_tests(complex(5325,2346));
|
||||
generic_complex_tests(complex(Integer(-243897),Integer(-49923874)));
|
||||
generic_complex_tests(complex(Integer(-543),Integer(763)));
|
||||
}
|
||||
|
||||
template<class T> void complex_grid_test( short N )
|
||||
{
|
||||
std::set<std::size_t> hashes;
|
||||
|
||||
for( short i = 0; i < N; ++i )
|
||||
{
|
||||
for( short j = 0; j < N; ++j )
|
||||
{
|
||||
hashes.insert( boost::hash< std::complex<T> >()( std::complex<T>( i, j ) ) );
|
||||
}
|
||||
}
|
||||
|
||||
BOOST_TEST_EQ( hashes.size(), static_cast<std::size_t>( N * N ) );
|
||||
}
|
||||
|
||||
int main()
|
||||
{
|
||||
// I've comments out the short and unsigned short tests
|
||||
// as they cause warnings and don't really test
|
||||
// anything that the other tests already deal with.
|
||||
|
||||
complex_float_tests((float*) 0);
|
||||
complex_float_tests((double*) 0);
|
||||
complex_float_tests((long double*) 0);
|
||||
//complex_integral_tests((short*) 0);
|
||||
complex_integral_tests((int*) 0);
|
||||
complex_integral_tests((long*) 0);
|
||||
//complex_integral_tests((unsigned short*) 0);
|
||||
complex_integral_tests((unsigned int*) 0);
|
||||
complex_integral_tests((unsigned long*) 0);
|
||||
|
||||
complex_grid_test<int>( 16 );
|
||||
complex_grid_test<float>( 7 );
|
||||
complex_grid_test<double>( 16 );
|
||||
complex_grid_test<long double>( 15 );
|
||||
|
||||
return boost::report_errors();
|
||||
}
|
||||
|
||||
#endif // BOOST_HASH_TEST_EXTENSIONS
|
52
test/hash_container_test.cpp
Normal file
52
test/hash_container_test.cpp
Normal file
@ -0,0 +1,52 @@
|
||||
// Copyright 2022 Peter Dimov.
|
||||
// Distributed under the Boost Software License, Version 1.0.
|
||||
// https://www.boost.org/LICENSE_1_0.txt
|
||||
|
||||
#include <boost/container_hash/hash.hpp>
|
||||
#include <boost/core/lightweight_test.hpp>
|
||||
#include <boost/config.hpp>
|
||||
#include <vector>
|
||||
#include <deque>
|
||||
#include <list>
|
||||
#if !defined(BOOST_NO_CXX11_HDR_FORWARD_LIST)
|
||||
# include <forward_list>
|
||||
#endif
|
||||
|
||||
template<class T> std::size_t hv( T const& t )
|
||||
{
|
||||
return boost::hash<T>()( t );
|
||||
}
|
||||
|
||||
template<class T> void test()
|
||||
{
|
||||
for( std::size_t i = 0; i < 8; ++i )
|
||||
{
|
||||
std::vector<T> v( i );
|
||||
std::size_t h0 = hv( v );
|
||||
|
||||
std::deque<T> d( v.begin(), v.end() );
|
||||
BOOST_TEST_EQ( h0, hv( d ) );
|
||||
|
||||
std::list<T> l( v.begin(), v.end() );
|
||||
BOOST_TEST_EQ( h0, hv( l ) );
|
||||
|
||||
#if !defined(BOOST_NO_CXX11_HDR_FORWARD_LIST)
|
||||
|
||||
std::forward_list<T> f( v.begin(), v.end() );
|
||||
BOOST_TEST_EQ( h0, hv( f ) );
|
||||
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
int main()
|
||||
{
|
||||
test<char>();
|
||||
test<unsigned char>();
|
||||
test<signed char>();
|
||||
test<int>();
|
||||
test<float>();
|
||||
test<double>();
|
||||
|
||||
return boost::report_errors();
|
||||
}
|
100
test/hash_custom_test.cpp
Normal file
100
test/hash_custom_test.cpp
Normal file
@ -0,0 +1,100 @@
|
||||
|
||||
// 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)
|
||||
|
||||
#include "./config.hpp"
|
||||
#include <boost/config.hpp>
|
||||
#include <cstddef>
|
||||
|
||||
namespace test
|
||||
{
|
||||
struct custom
|
||||
{
|
||||
int value_;
|
||||
|
||||
std::size_t hash() const
|
||||
{
|
||||
return static_cast<std::size_t>(value_ * 10);
|
||||
}
|
||||
|
||||
#if !defined(BOOST_NO_ARGUMENT_DEPENDENT_LOOKUP)
|
||||
friend std::size_t hash_value(custom const& x )
|
||||
{
|
||||
return x.hash();
|
||||
}
|
||||
#endif
|
||||
|
||||
custom(int x) : value_(x) {}
|
||||
};
|
||||
}
|
||||
|
||||
#if defined(BOOST_NO_ARGUMENT_DEPENDENT_LOOKUP)
|
||||
namespace boost
|
||||
{
|
||||
std::size_t hash_value(test::custom x)
|
||||
{
|
||||
return x.hash();
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
#include "./config.hpp"
|
||||
|
||||
#ifdef BOOST_HASH_TEST_EXTENSIONS
|
||||
# ifdef BOOST_HASH_TEST_STD_INCLUDES
|
||||
# include <functional>
|
||||
# else
|
||||
# include <boost/container_hash/hash.hpp>
|
||||
# endif
|
||||
#endif
|
||||
|
||||
#include <boost/core/lightweight_test.hpp>
|
||||
|
||||
#ifdef BOOST_HASH_TEST_EXTENSIONS
|
||||
|
||||
#include <vector>
|
||||
#include <string>
|
||||
#include <cctype>
|
||||
|
||||
void custom_tests()
|
||||
{
|
||||
BOOST_HASH_TEST_NAMESPACE::hash<test::custom> custom_hasher;
|
||||
BOOST_TEST(custom_hasher(10) == 100u);
|
||||
test::custom x(55);
|
||||
BOOST_TEST(custom_hasher(x) == 550u);
|
||||
|
||||
{
|
||||
using namespace BOOST_HASH_TEST_NAMESPACE;
|
||||
BOOST_TEST(custom_hasher(x) == hash_value(x));
|
||||
}
|
||||
|
||||
std::vector<test::custom> custom_vector;
|
||||
custom_vector.push_back(5);
|
||||
custom_vector.push_back(25);
|
||||
custom_vector.push_back(35);
|
||||
|
||||
std::size_t seed = 0;
|
||||
BOOST_HASH_TEST_NAMESPACE::hash_combine(seed, test::custom(5));
|
||||
BOOST_HASH_TEST_NAMESPACE::hash_combine(seed, test::custom(25));
|
||||
BOOST_HASH_TEST_NAMESPACE::hash_combine(seed, test::custom(35));
|
||||
|
||||
std::size_t seed2 = 0;
|
||||
BOOST_HASH_TEST_NAMESPACE::hash_combine(seed2, 50u);
|
||||
BOOST_HASH_TEST_NAMESPACE::hash_combine(seed2, 250u);
|
||||
BOOST_HASH_TEST_NAMESPACE::hash_combine(seed2, 350u);
|
||||
|
||||
BOOST_TEST(seed == BOOST_HASH_TEST_NAMESPACE::hash_range(
|
||||
custom_vector.begin(), custom_vector.end()));
|
||||
BOOST_TEST(seed == seed2);
|
||||
}
|
||||
|
||||
#endif // BOOST_HASH_TEST_EXTENSIONS
|
||||
|
||||
int main()
|
||||
{
|
||||
#ifdef BOOST_HASH_TEST_EXTENSIONS
|
||||
custom_tests();
|
||||
#endif
|
||||
return boost::report_errors();
|
||||
}
|
35
test/hash_deque_test.cpp
Normal file
35
test/hash_deque_test.cpp
Normal file
@ -0,0 +1,35 @@
|
||||
|
||||
// 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)
|
||||
|
||||
#include "./config.hpp"
|
||||
|
||||
#ifdef BOOST_HASH_TEST_EXTENSIONS
|
||||
# ifdef BOOST_HASH_TEST_STD_INCLUDES
|
||||
# include <functional>
|
||||
# else
|
||||
# include <boost/container_hash/hash.hpp>
|
||||
# endif
|
||||
#endif
|
||||
|
||||
#include <boost/core/lightweight_test.hpp>
|
||||
|
||||
#ifdef BOOST_HASH_TEST_EXTENSIONS
|
||||
|
||||
#include <deque>
|
||||
|
||||
using std::deque;
|
||||
#define CONTAINER_TYPE deque
|
||||
#include "./hash_sequence_test.hpp"
|
||||
|
||||
#endif // BOOST_HASH_TEST_EXTENSIONS
|
||||
|
||||
int main()
|
||||
{
|
||||
#ifdef BOOST_HASH_TEST_EXTENSIONS
|
||||
deque_tests::deque_hash_integer_tests();
|
||||
#endif
|
||||
|
||||
return boost::report_errors();
|
||||
}
|
63
test/hash_enum_test.cpp
Normal file
63
test/hash_enum_test.cpp
Normal file
@ -0,0 +1,63 @@
|
||||
|
||||
// Copyright 2012 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"
|
||||
|
||||
#ifdef BOOST_HASH_TEST_STD_INCLUDES
|
||||
# include <functional>
|
||||
#else
|
||||
# include <boost/container_hash/hash.hpp>
|
||||
#endif
|
||||
|
||||
#include <boost/core/lightweight_test.hpp>
|
||||
#include "./compile_time.hpp"
|
||||
|
||||
namespace test {
|
||||
enum enum_override { enum_override1, enum_override2 };
|
||||
std::size_t hash_value(enum_override) { return 896532; }
|
||||
|
||||
enum enum1 { enum1a };
|
||||
enum enum2 { enum2a, enum2b };
|
||||
enum enum3 { enum3a = 574, enum3b };
|
||||
enum enum4 { enum4a = -12574, enum4b };
|
||||
}
|
||||
|
||||
int main() {
|
||||
compile_time_tests((test::enum1*) 0);
|
||||
compile_time_tests((test::enum2*) 0);
|
||||
compile_time_tests((test::enum3*) 0);
|
||||
compile_time_tests((test::enum4*) 0);
|
||||
compile_time_tests((test::enum_override*) 0);
|
||||
|
||||
BOOST_HASH_TEST_NAMESPACE::hash<test::enum1> hash1;
|
||||
BOOST_HASH_TEST_NAMESPACE::hash<test::enum2> hash2;
|
||||
BOOST_HASH_TEST_NAMESPACE::hash<test::enum3> hash3;
|
||||
BOOST_HASH_TEST_NAMESPACE::hash<test::enum4> hash4;
|
||||
|
||||
BOOST_TEST(hash1(test::enum1a) == hash1(test::enum1a));
|
||||
|
||||
BOOST_TEST(hash2(test::enum2a) == hash2(test::enum2a));
|
||||
BOOST_TEST(hash2(test::enum2a) != hash2(test::enum2b));
|
||||
BOOST_TEST(hash2(test::enum2b) == hash2(test::enum2b));
|
||||
|
||||
BOOST_TEST(hash3(test::enum3a) == hash3(test::enum3a));
|
||||
BOOST_TEST(hash3(test::enum3a) != hash3(test::enum3b));
|
||||
BOOST_TEST(hash3(test::enum3b) == hash3(test::enum3b));
|
||||
|
||||
BOOST_TEST(hash4(test::enum4a) == hash4(test::enum4a));
|
||||
BOOST_TEST(hash4(test::enum4a) != hash4(test::enum4b));
|
||||
BOOST_TEST(hash4(test::enum4b) == hash4(test::enum4b));
|
||||
|
||||
BOOST_HASH_TEST_NAMESPACE::hash<test::enum_override> hash_override;
|
||||
|
||||
BOOST_TEST(hash_override(test::enum_override1) ==
|
||||
hash_override(test::enum_override1));
|
||||
BOOST_TEST(hash_override(test::enum_override1) ==
|
||||
hash_override(test::enum_override2));
|
||||
BOOST_TEST(hash_override(test::enum_override1) ==
|
||||
hash_override(test::enum_override1));
|
||||
|
||||
return boost::report_errors();
|
||||
}
|
18
test/hash_float_test.cpp
Normal file
18
test/hash_float_test.cpp
Normal file
@ -0,0 +1,18 @@
|
||||
|
||||
// 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)
|
||||
|
||||
#include "hash_float_test.hpp"
|
||||
|
||||
int main()
|
||||
{
|
||||
std::cerr<<"Compiler: "<<BOOST_COMPILER<<"\n";
|
||||
std::cerr<<"Platform: "<<BOOST_PLATFORM<<"\n";
|
||||
std::cerr<<"Library: "<<BOOST_STDLIB<<"\n\n";
|
||||
|
||||
float_tests("float", (float*) 0);
|
||||
float_tests("double", (double*) 0);
|
||||
|
||||
return boost::report_errors();
|
||||
}
|
295
test/hash_float_test.hpp
Normal file
295
test/hash_float_test.hpp
Normal file
@ -0,0 +1,295 @@
|
||||
|
||||
// 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)
|
||||
|
||||
#include "./config.hpp"
|
||||
|
||||
#ifdef BOOST_HASH_TEST_STD_INCLUDES
|
||||
# include <functional>
|
||||
#else
|
||||
# include <boost/container_hash/hash.hpp>
|
||||
#endif
|
||||
|
||||
#include <boost/core/lightweight_test.hpp>
|
||||
|
||||
#include <cmath>
|
||||
#include <boost/container_hash/detail/limits.hpp>
|
||||
#include <boost/config/workaround.hpp>
|
||||
|
||||
#include <iostream>
|
||||
|
||||
#if defined(BOOST_MSVC)
|
||||
#pragma warning(push)
|
||||
#pragma warning(disable:4127) // conditional expression is constant
|
||||
#pragma warning(disable:4723) // conditional expression is constant
|
||||
#if BOOST_MSVC < 1400
|
||||
#pragma warning(disable:4267) // conversion from 'size_t' to 'unsigned int',
|
||||
// possible loss of data
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#if ( defined(__GNUC__) || defined(__clang__) ) && !defined(BOOST_INTEL_CXX_VERSION)
|
||||
#pragma GCC diagnostic ignored "-Wfloat-equal"
|
||||
#endif
|
||||
|
||||
char const* float_type(float*) { return "float"; }
|
||||
char const* float_type(double*) { return "double"; }
|
||||
char const* float_type(long double*) { return "long double"; }
|
||||
|
||||
template <class T>
|
||||
void float_tests(char const* name, T* = 0)
|
||||
{
|
||||
std::cerr
|
||||
<< "\n"
|
||||
<< "Testing " BOOST_STRINGIZE(BOOST_HASH_TEST_NAMESPACE) "::hash<"
|
||||
<< name
|
||||
<< ">\n"
|
||||
<< "\n"
|
||||
<< "boost::hash_detail::limits<T>::digits = "
|
||||
<< boost::hash_detail::limits<T>::digits<< "\n"
|
||||
<< "boost::hash_detail::limits<int>::digits = "
|
||||
<< boost::hash_detail::limits<int>::digits<< "\n"
|
||||
<< "boost::hash_detail::limits<std::size_t>::digits = "
|
||||
<< boost::hash_detail::limits<std::size_t>::digits
|
||||
<< "\n"
|
||||
<< "\n"
|
||||
;
|
||||
|
||||
BOOST_HASH_TEST_NAMESPACE::hash<T> x1;
|
||||
|
||||
T zero = 0;
|
||||
T minus_zero = (T) -1 * zero;
|
||||
|
||||
BOOST_TEST(zero == minus_zero);
|
||||
BOOST_TEST(x1(zero) == x1(minus_zero));
|
||||
|
||||
#if defined(BOOST_HASH_TEST_EXTENSIONS)
|
||||
BOOST_TEST(x1(zero) == BOOST_HASH_TEST_NAMESPACE::hash_value(zero));
|
||||
BOOST_TEST(x1(minus_zero) == BOOST_HASH_TEST_NAMESPACE::hash_value(minus_zero));
|
||||
#endif
|
||||
|
||||
BOOST_TEST(x1(zero) != x1(0.5));
|
||||
BOOST_TEST(x1(minus_zero) != x1(0.5));
|
||||
BOOST_TEST(x1(0.5) != x1(-0.5));
|
||||
BOOST_TEST(x1(1) != x1(-1));
|
||||
|
||||
using namespace std;
|
||||
|
||||
// Doing anything with infinity causes borland to crash.
|
||||
#if defined(BOOST_BORLANDC)
|
||||
std::cerr
|
||||
<< "Not running infinity checks on Borland, as it causes it to crash."
|
||||
"\n";
|
||||
#else
|
||||
if(boost::hash_detail::limits<T>::has_infinity) {
|
||||
T infinity = -log(zero);
|
||||
T infinity2 = (T) 1. / zero;
|
||||
T infinity3 = (T) -1. / minus_zero;
|
||||
T infinity4 = boost::hash_detail::limits<T>::infinity();
|
||||
|
||||
T minus_infinity = log(zero);
|
||||
T minus_infinity2 = (T) -1. / zero;
|
||||
T minus_infinity3 = (T) 1. / minus_zero;
|
||||
|
||||
#if defined(BOOST_HASH_TEST_EXTENSIONS)
|
||||
BOOST_TEST(x1(infinity) == BOOST_HASH_TEST_NAMESPACE::hash_value(infinity));
|
||||
BOOST_TEST(x1(minus_infinity)
|
||||
== BOOST_HASH_TEST_NAMESPACE::hash_value(minus_infinity));
|
||||
#endif
|
||||
|
||||
if(infinity == infinity2)
|
||||
BOOST_TEST(x1(infinity) == x1(infinity2));
|
||||
if(infinity == infinity3)
|
||||
BOOST_TEST(x1(infinity) == x1(infinity3));
|
||||
if(infinity == infinity4)
|
||||
BOOST_TEST(x1(infinity) == x1(infinity4));
|
||||
|
||||
if(minus_infinity == minus_infinity2)
|
||||
BOOST_TEST(x1(minus_infinity) == x1(minus_infinity2));
|
||||
if(minus_infinity == minus_infinity3)
|
||||
BOOST_TEST(x1(minus_infinity) == x1(minus_infinity3));
|
||||
|
||||
BOOST_TEST(infinity != minus_infinity);
|
||||
|
||||
if(x1(infinity) == x1(minus_infinity)) {
|
||||
std::cerr<<"x1(infinity) == x1(-infinity) == "<<x1(infinity)<<"\n";
|
||||
}
|
||||
|
||||
// This should really be 'has_denorm == denorm_present' but some
|
||||
// compilers don't have 'denorm_present'. See also a later use.
|
||||
if(boost::hash_detail::limits<T>::has_denorm) {
|
||||
if(x1(boost::hash_detail::limits<T>::denorm_min()) == x1(infinity))
|
||||
{
|
||||
std::cerr
|
||||
<< "x1(denorm_min) == x1(infinity) == "
|
||||
<< x1(infinity)
|
||||
<< "\n";
|
||||
}
|
||||
|
||||
if(x1(boost::hash_detail::limits<T>::denorm_min()) ==
|
||||
x1(minus_infinity))
|
||||
{
|
||||
std::cerr
|
||||
<< "x1(denorm_min) == x1(-infinity) == "
|
||||
<< x1(minus_infinity)
|
||||
<< "\n";
|
||||
}
|
||||
}
|
||||
|
||||
if(boost::hash_detail::limits<T>::has_quiet_NaN) {
|
||||
if(x1(boost::hash_detail::limits<T>::quiet_NaN()) == x1(infinity))
|
||||
{
|
||||
std::cerr
|
||||
<< "x1(quiet_NaN) == x1(infinity) == "
|
||||
<< x1(infinity)
|
||||
<< "\n";
|
||||
}
|
||||
|
||||
if(x1(boost::hash_detail::limits<T>::quiet_NaN()) ==
|
||||
x1(minus_infinity))
|
||||
{
|
||||
std::cerr
|
||||
<< "x1(quiet_NaN) == x1(-infinity) == "
|
||||
<< x1(minus_infinity)
|
||||
<< "\n";
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
T max = (boost::hash_detail::limits<T>::max)();
|
||||
T half_max = max / 2;
|
||||
T quarter_max = max / 4;
|
||||
T three_quarter_max = max - quarter_max;
|
||||
|
||||
// Check the limits::max is in range.
|
||||
BOOST_TEST(max != half_max);
|
||||
BOOST_TEST(max != quarter_max);
|
||||
BOOST_TEST(max != three_quarter_max);
|
||||
BOOST_TEST(half_max != quarter_max);
|
||||
BOOST_TEST(half_max != three_quarter_max);
|
||||
BOOST_TEST(quarter_max != three_quarter_max);
|
||||
|
||||
BOOST_TEST(max != -max);
|
||||
BOOST_TEST(half_max != -half_max);
|
||||
BOOST_TEST(quarter_max != -quarter_max);
|
||||
BOOST_TEST(three_quarter_max != -three_quarter_max);
|
||||
|
||||
|
||||
#if defined(BOOST_HASH_TEST_EXTENSIONS)
|
||||
BOOST_TEST(x1(max) == BOOST_HASH_TEST_NAMESPACE::hash_value(max));
|
||||
BOOST_TEST(x1(half_max) == BOOST_HASH_TEST_NAMESPACE::hash_value(half_max));
|
||||
BOOST_TEST(x1(quarter_max) == BOOST_HASH_TEST_NAMESPACE::hash_value(quarter_max));
|
||||
BOOST_TEST(x1(three_quarter_max) ==
|
||||
BOOST_HASH_TEST_NAMESPACE::hash_value(three_quarter_max));
|
||||
#endif
|
||||
|
||||
// The '!=' tests could legitimately fail, but with my hash it indicates a
|
||||
// bug.
|
||||
BOOST_TEST(x1(max) == x1(max));
|
||||
BOOST_TEST(x1(max) != x1(quarter_max));
|
||||
BOOST_TEST(x1(max) != x1(half_max));
|
||||
BOOST_TEST(x1(max) != x1(three_quarter_max));
|
||||
BOOST_TEST(x1(quarter_max) == x1(quarter_max));
|
||||
BOOST_TEST(x1(quarter_max) != x1(half_max));
|
||||
BOOST_TEST(x1(quarter_max) != x1(three_quarter_max));
|
||||
BOOST_TEST(x1(half_max) == x1(half_max));
|
||||
BOOST_TEST(x1(half_max) != x1(three_quarter_max));
|
||||
BOOST_TEST(x1(three_quarter_max) == x1(three_quarter_max));
|
||||
|
||||
BOOST_TEST(x1(max) != x1(-max));
|
||||
BOOST_TEST(x1(half_max) != x1(-half_max));
|
||||
BOOST_TEST(x1(quarter_max) != x1(-quarter_max));
|
||||
BOOST_TEST(x1(three_quarter_max) != x1(-three_quarter_max));
|
||||
|
||||
|
||||
// Intel with gcc stdlib sometimes segfaults on calls to asin and acos.
|
||||
#if !((defined(__INTEL_COMPILER) || defined(__ICL) || \
|
||||
defined(__ICC) || defined(__ECC)) && \
|
||||
(defined(__GLIBCPP__) || defined(__GLIBCXX__)))
|
||||
T v1 = asin((T) 1);
|
||||
T v2 = acos((T) 0);
|
||||
if(v1 == v2)
|
||||
BOOST_TEST(x1(v1) == x1(v2));
|
||||
|
||||
#if defined(BOOST_HASH_TEST_EXTENSIONS)
|
||||
BOOST_TEST(x1(v1) == BOOST_HASH_TEST_NAMESPACE::hash_value(v1));
|
||||
BOOST_TEST(x1(v2) == BOOST_HASH_TEST_NAMESPACE::hash_value(v2));
|
||||
#endif
|
||||
|
||||
#endif
|
||||
|
||||
#if defined(BOOST_HASH_TEST_EXTENSIONS)
|
||||
BOOST_TEST(x1(boost::hash_detail::limits<T>::epsilon()) ==
|
||||
BOOST_HASH_TEST_NAMESPACE::hash_value(
|
||||
boost::hash_detail::limits<T>::epsilon()));
|
||||
#endif
|
||||
|
||||
BOOST_TEST(boost::hash_detail::limits<T>::epsilon() != (T) 0);
|
||||
if(x1(boost::hash_detail::limits<T>::epsilon()) == x1((T) 0))
|
||||
std::cerr<<"x1(epsilon) == x1(0) == "<<x1((T) 0)<<"\n";
|
||||
|
||||
BOOST_TEST(-boost::hash_detail::limits<T>::epsilon() != (T) 0);
|
||||
if(x1(-boost::hash_detail::limits<T>::epsilon()) == x1((T) 0))
|
||||
std::cerr<<"x1(-epsilon) == x1(0) == "<<x1((T) 0)<<"\n";
|
||||
|
||||
BOOST_TEST((T) 1 + boost::hash_detail::limits<T>::epsilon() != (T) 1);
|
||||
if(x1((T) 1 + boost::hash_detail::limits<T>::epsilon()) == x1((T) 1))
|
||||
std::cerr<<"x1(1 + epsilon) == x1(1) == "<<x1((T) 1)<<"\n";
|
||||
|
||||
BOOST_TEST((T) 1 - boost::hash_detail::limits<T>::epsilon() != (T) 1);
|
||||
if(x1((T) 1 - boost::hash_detail::limits<T>::epsilon()) == x1((T) 1))
|
||||
std::cerr<<"x1(1 - epsilon) == x1(1) == "<<x1((T) 1)<<"\n";
|
||||
|
||||
BOOST_TEST((T) -1 + boost::hash_detail::limits<T>::epsilon() != (T) -1);
|
||||
if(x1((T) -1 + boost::hash_detail::limits<T>::epsilon()) == x1((T) -1))
|
||||
std::cerr<<"x1(-1 + epsilon) == x1(-1) == "<<x1((T) -1)<<"\n";
|
||||
|
||||
BOOST_TEST((T) -1 - boost::hash_detail::limits<T>::epsilon() != (T) -1);
|
||||
if(x1((T) -1 - boost::hash_detail::limits<T>::epsilon()) == x1((T) -1))
|
||||
std::cerr<<"x1(-1 - epsilon) == x1(-1) == "<<x1((T) -1)<<"\n";
|
||||
|
||||
// As before.
|
||||
if(boost::hash_detail::limits<T>::has_denorm) {
|
||||
if(x1(boost::hash_detail::limits<T>::denorm_min()) == x1(zero)) {
|
||||
std::cerr<<"x1(denorm_min) == x1(zero) == "<<x1(zero)<<"\n";
|
||||
}
|
||||
#if !BOOST_WORKAROUND(__DECCXX_VER,<70190006) && defined(BOOST_HASH_TEST_EXTENSIONS)
|
||||
// The Tru64/CXX standard library prior to 7.1 contains a bug in the
|
||||
// specialization of boost::hash_detail::limits::denorm_min() for long
|
||||
// doubles which causes this test to fail.
|
||||
if(x1(boost::hash_detail::limits<T>::denorm_min()) !=
|
||||
BOOST_HASH_TEST_NAMESPACE::hash_value(
|
||||
boost::hash_detail::limits<T>::denorm_min()))
|
||||
{
|
||||
std::cerr
|
||||
<< "x1(boost::hash_detail::limits<T>::denorm_min()) = "
|
||||
<< x1(boost::hash_detail::limits<T>::denorm_min())
|
||||
<< "\nhash_value(boost::hash_detail::limits<T>::denorm_min())"
|
||||
" = "
|
||||
<< BOOST_HASH_TEST_NAMESPACE::hash_value(
|
||||
boost::hash_detail::limits<T>::denorm_min())
|
||||
<< "\nx1(0) = "
|
||||
<< x1(0)
|
||||
<< "\n";
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
// NaN also causes borland to crash.
|
||||
#if !defined(BOOST_BORLANDC) && defined(BOOST_HASH_TEST_EXTENSIONS)
|
||||
if(boost::hash_detail::limits<T>::has_quiet_NaN) {
|
||||
if(x1(boost::hash_detail::limits<T>::quiet_NaN()) == x1(1.0)) {
|
||||
std::cerr<<"x1(quiet_NaN) == x1(1.0) == "<<x1(1.0)<<"\n";
|
||||
}
|
||||
BOOST_TEST(x1(boost::hash_detail::limits<T>::quiet_NaN()) ==
|
||||
BOOST_HASH_TEST_NAMESPACE::hash_value(
|
||||
boost::hash_detail::limits<T>::quiet_NaN()));
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
#if defined(BOOST_MSVC)
|
||||
#pragma warning(pop)
|
||||
#endif
|
59
test/hash_forward_list_test.cpp
Normal file
59
test/hash_forward_list_test.cpp
Normal file
@ -0,0 +1,59 @@
|
||||
// Copyright 2021 Peter Dimov.
|
||||
// Distributed under the Boost Software License, Version 1.0.
|
||||
// https://www.boost.org/LICENSE_1_0.txt
|
||||
|
||||
#if defined(__GNUC__) && __GNUC__ == 8
|
||||
# pragma GCC diagnostic ignored "-Wsign-conversion"
|
||||
#endif
|
||||
|
||||
#include <boost/container_hash/hash.hpp>
|
||||
#include <boost/core/lightweight_test.hpp>
|
||||
#include <boost/config.hpp>
|
||||
#include <boost/config/pragma_message.hpp>
|
||||
|
||||
#if defined(BOOST_NO_CXX11_HDR_FORWARD_LIST)
|
||||
|
||||
BOOST_PRAGMA_MESSAGE( "Test skipped, BOOST_NO_CXX11_HDR_FORWARD_LIST is defined" )
|
||||
int main() {}
|
||||
|
||||
#else
|
||||
|
||||
#include <forward_list>
|
||||
|
||||
template<class T> void test()
|
||||
{
|
||||
typedef std::forward_list<T> list;
|
||||
typedef boost::hash<list> hash;
|
||||
|
||||
int const N = 32;
|
||||
|
||||
std::size_t h[ N ];
|
||||
|
||||
list v;
|
||||
|
||||
for( int i = 0; i < N; ++i )
|
||||
{
|
||||
h[ i ] = hash()( v );
|
||||
|
||||
BOOST_TEST_EQ( h[ i ], hash()( v ) );
|
||||
|
||||
for( int j = 0; j < i; ++j )
|
||||
{
|
||||
BOOST_TEST_NE( h[ j ], h[ i ] );
|
||||
}
|
||||
|
||||
v.push_front( T() );
|
||||
}
|
||||
}
|
||||
|
||||
int main()
|
||||
{
|
||||
test<int>();
|
||||
test<float>();
|
||||
test<double>();
|
||||
test< std::forward_list<int> >();
|
||||
|
||||
return boost::report_errors();
|
||||
}
|
||||
|
||||
#endif
|
103
test/hash_friend_test.cpp
Normal file
103
test/hash_friend_test.cpp
Normal file
@ -0,0 +1,103 @@
|
||||
|
||||
// Copyright 2006-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)
|
||||
|
||||
#include "./config.hpp"
|
||||
|
||||
#include <boost/config.hpp>
|
||||
#include <cstddef>
|
||||
|
||||
namespace test
|
||||
{
|
||||
template <class T>
|
||||
struct custom
|
||||
{
|
||||
int value_;
|
||||
|
||||
std::size_t hash() const
|
||||
{
|
||||
return static_cast<std::size_t>(value_ * 10);
|
||||
}
|
||||
|
||||
#if !defined(BOOST_NO_ARGUMENT_DEPENDENT_LOOKUP)
|
||||
friend std::size_t hash_value(custom const& x)
|
||||
{
|
||||
return x.hash();
|
||||
}
|
||||
#endif
|
||||
|
||||
custom(int x) : value_(x) {}
|
||||
};
|
||||
}
|
||||
|
||||
#if defined(BOOST_NO_ARGUMENT_DEPENDENT_LOOKUP)
|
||||
namespace boost
|
||||
{
|
||||
template <class T>
|
||||
std::size_t hash_value(test::custom<T> x)
|
||||
{
|
||||
return x.hash();
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
#include "./config.hpp"
|
||||
|
||||
#ifdef BOOST_HASH_TEST_EXTENSIONS
|
||||
# ifdef BOOST_HASH_TEST_STD_INCLUDES
|
||||
# include <functional>
|
||||
# else
|
||||
# include <boost/container_hash/hash.hpp>
|
||||
# endif
|
||||
#endif
|
||||
|
||||
#include <boost/core/lightweight_test.hpp>
|
||||
|
||||
#ifdef BOOST_HASH_TEST_EXTENSIONS
|
||||
|
||||
#include <vector>
|
||||
#include <string>
|
||||
#include <cctype>
|
||||
|
||||
void custom_tests()
|
||||
{
|
||||
BOOST_HASH_TEST_NAMESPACE::hash<test::custom<int> > custom_hasher;
|
||||
BOOST_TEST(custom_hasher(10) == 100u);
|
||||
test::custom<int> x(55);
|
||||
BOOST_TEST(custom_hasher(x) == 550u);
|
||||
|
||||
{
|
||||
using namespace BOOST_HASH_TEST_NAMESPACE;
|
||||
BOOST_TEST(custom_hasher(x) == hash_value(x));
|
||||
}
|
||||
|
||||
std::vector<test::custom<int> > custom_vector;
|
||||
custom_vector.push_back(5);
|
||||
custom_vector.push_back(25);
|
||||
custom_vector.push_back(35);
|
||||
|
||||
std::size_t seed = 0;
|
||||
BOOST_HASH_TEST_NAMESPACE::hash_combine(seed, test::custom<int>(5));
|
||||
BOOST_HASH_TEST_NAMESPACE::hash_combine(seed, test::custom<int>(25));
|
||||
BOOST_HASH_TEST_NAMESPACE::hash_combine(seed, test::custom<int>(35));
|
||||
|
||||
std::size_t seed2 = 0;
|
||||
BOOST_HASH_TEST_NAMESPACE::hash_combine(seed2, 50u);
|
||||
BOOST_HASH_TEST_NAMESPACE::hash_combine(seed2, 250u);
|
||||
BOOST_HASH_TEST_NAMESPACE::hash_combine(seed2, 350u);
|
||||
|
||||
BOOST_TEST(seed == BOOST_HASH_TEST_NAMESPACE::hash_range(
|
||||
custom_vector.begin(), custom_vector.end()));
|
||||
BOOST_TEST(seed == seed2);
|
||||
}
|
||||
|
||||
#endif // BOOST_HASH_TEST_EXTENSIONS
|
||||
|
||||
int main()
|
||||
{
|
||||
#ifdef BOOST_HASH_TEST_EXTENSIONS
|
||||
custom_tests();
|
||||
#endif
|
||||
return boost::report_errors();
|
||||
}
|
30
test/hash_fs_path_test.cpp
Normal file
30
test/hash_fs_path_test.cpp
Normal file
@ -0,0 +1,30 @@
|
||||
// Copyright 2022 Peter Dimov.
|
||||
// Distributed under the Boost Software License, Version 1.0.
|
||||
// https://www.boost.org/LICENSE_1_0.txt
|
||||
|
||||
#if defined(_MSC_VER)
|
||||
# pragma warning(disable: 4714) // forceinline not inlined
|
||||
#endif
|
||||
|
||||
#if defined(__GNUC__) || defined(__clang__)
|
||||
# pragma GCC diagnostic ignored "-Wsign-conversion"
|
||||
#endif
|
||||
|
||||
#include <boost/filesystem/path.hpp>
|
||||
#include <boost/container_hash/hash.hpp>
|
||||
#include <boost/core/lightweight_test.hpp>
|
||||
|
||||
template<class T> std::size_t hv( T const& t )
|
||||
{
|
||||
return boost::hash<T>()( t );
|
||||
}
|
||||
|
||||
int main()
|
||||
{
|
||||
boost::filesystem::path p1( "/foo/bar" );
|
||||
boost::filesystem::path p2( "/foo/baz" );
|
||||
|
||||
BOOST_TEST_NE( hv( p1 ), hv( p2 ) );
|
||||
|
||||
return boost::report_errors();
|
||||
}
|
57
test/hash_function_pointer_test.cpp
Normal file
57
test/hash_function_pointer_test.cpp
Normal file
@ -0,0 +1,57 @@
|
||||
|
||||
// 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)
|
||||
|
||||
#include "./config.hpp"
|
||||
|
||||
#ifdef BOOST_HASH_TEST_STD_INCLUDES
|
||||
# include <functional>
|
||||
#else
|
||||
# include <boost/container_hash/hash.hpp>
|
||||
#endif
|
||||
|
||||
#include <boost/core/lightweight_test.hpp>
|
||||
#include "./compile_time.hpp"
|
||||
|
||||
void void_func1() { static int x = 1; ++x; }
|
||||
void void_func2() { static int x = 2; --x; }
|
||||
int int_func1(int) { return 0; }
|
||||
int int_func2(int) { return 1; }
|
||||
|
||||
void function_pointer_tests()
|
||||
{
|
||||
compile_time_tests((void(**)()) 0);
|
||||
compile_time_tests((int(**)(int)) 0);
|
||||
|
||||
BOOST_HASH_TEST_NAMESPACE::hash<void(*)()> hasher_void;
|
||||
BOOST_HASH_TEST_NAMESPACE::hash<int(*)(int)> hasher_int;
|
||||
|
||||
BOOST_TEST(&void_func1 != &void_func2);
|
||||
BOOST_TEST(&int_func1 != &int_func2);
|
||||
|
||||
BOOST_TEST(hasher_void(0) == hasher_void(0));
|
||||
BOOST_TEST(hasher_void(&void_func1) == hasher_void(&void_func1));
|
||||
BOOST_TEST(hasher_void(&void_func1) != hasher_void(&void_func2));
|
||||
BOOST_TEST(hasher_void(&void_func1) != hasher_void(0));
|
||||
BOOST_TEST(hasher_int(0) == hasher_int(0));
|
||||
BOOST_TEST(hasher_int(&int_func1) == hasher_int(&int_func1));
|
||||
BOOST_TEST(hasher_int(&int_func1) != hasher_int(&int_func2));
|
||||
BOOST_TEST(hasher_int(&int_func1) != hasher_int(0));
|
||||
#if defined(BOOST_HASH_TEST_EXTENSIONS)
|
||||
BOOST_TEST(hasher_void(&void_func1)
|
||||
== BOOST_HASH_TEST_NAMESPACE::hash_value(&void_func1));
|
||||
BOOST_TEST(hasher_int(&int_func1)
|
||||
== BOOST_HASH_TEST_NAMESPACE::hash_value(&int_func1));
|
||||
|
||||
// This isn't specified in Peter's proposal:
|
||||
BOOST_TEST(hasher_void(0) == 0);
|
||||
#endif
|
||||
}
|
||||
|
||||
int main()
|
||||
{
|
||||
function_pointer_tests();
|
||||
|
||||
return boost::report_errors();
|
||||
}
|
104
test/hash_fwd_test.hpp
Normal file
104
test/hash_fwd_test.hpp
Normal file
@ -0,0 +1,104 @@
|
||||
|
||||
// Copyright 2006-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)
|
||||
|
||||
#include "./config.hpp"
|
||||
|
||||
#if defined(BOOST_HASH_TEST_EXTENSIONS) && !defined(BOOST_HASH_TEST_STD_INCLUDES)
|
||||
#include <boost/container_hash/hash_fwd.hpp>
|
||||
|
||||
#include <boost/config.hpp>
|
||||
#include <cstddef>
|
||||
#include <vector>
|
||||
|
||||
namespace test {
|
||||
|
||||
template <class T>
|
||||
struct test_type1
|
||||
{
|
||||
T value;
|
||||
test_type1(T const& x) : value(x) {}
|
||||
};
|
||||
|
||||
#if !defined(BOOST_NO_ARGUMENT_DEPENDENT_LOOKUP)
|
||||
template <class T>
|
||||
std::size_t hash_value(test_type1<T> const& x)
|
||||
{
|
||||
BOOST_HASH_TEST_NAMESPACE::hash<T> hasher;
|
||||
return hasher(x.value);
|
||||
}
|
||||
#endif
|
||||
|
||||
template <class T>
|
||||
struct test_type2
|
||||
{
|
||||
T value1, value2;
|
||||
test_type2(T const& x, T const& y) : value1(x), value2(y) {}
|
||||
};
|
||||
|
||||
#if !defined(BOOST_NO_ARGUMENT_DEPENDENT_LOOKUP)
|
||||
template <class T>
|
||||
std::size_t hash_value(test_type2<T> const& x)
|
||||
{
|
||||
std::size_t seed = 0;
|
||||
BOOST_HASH_TEST_NAMESPACE::hash_combine(seed, x.value1);
|
||||
BOOST_HASH_TEST_NAMESPACE::hash_combine(seed, x.value2);
|
||||
return seed;
|
||||
}
|
||||
#endif
|
||||
|
||||
template <class T>
|
||||
struct test_type3
|
||||
{
|
||||
std::vector<T> values;
|
||||
test_type3(typename std::vector<T>::iterator x,
|
||||
typename std::vector<T>::iterator y) : values(x, y) {}
|
||||
};
|
||||
|
||||
#if !defined(BOOST_NO_ARGUMENT_DEPENDENT_LOOKUP)
|
||||
template <class T>
|
||||
std::size_t hash_value(test_type3<T> const& x)
|
||||
{
|
||||
std::size_t seed =
|
||||
BOOST_HASH_TEST_NAMESPACE::hash_range(x.values.begin(), x.values.end());
|
||||
BOOST_HASH_TEST_NAMESPACE::hash_range(seed, x.values.begin(), x.values.end());
|
||||
return seed;
|
||||
}
|
||||
#endif
|
||||
|
||||
}
|
||||
|
||||
#if defined(BOOST_NO_ARGUMENT_DEPENDENT_LOOKUP)
|
||||
|
||||
namespace boost
|
||||
{
|
||||
template <class T>
|
||||
std::size_t hash_value(test::test_type1<T> const& x)
|
||||
{
|
||||
BOOST_HASH_TEST_NAMESPACE::hash<T> hasher;
|
||||
return hasher(x.value);
|
||||
}
|
||||
|
||||
template <class T>
|
||||
std::size_t hash_value(test::test_type2<T> const& x)
|
||||
{
|
||||
std::size_t seed = 0;
|
||||
BOOST_HASH_TEST_NAMESPACE::hash_combine(seed, x.value1);
|
||||
BOOST_HASH_TEST_NAMESPACE::hash_combine(seed, x.value2);
|
||||
return seed;
|
||||
}
|
||||
|
||||
template <class T>
|
||||
std::size_t hash_value(test::test_type3<T> const& x)
|
||||
{
|
||||
std::size_t seed =
|
||||
BOOST_HASH_TEST_NAMESPACE::hash_range(x.values.begin(), x.values.end());
|
||||
BOOST_HASH_TEST_NAMESPACE::hash_range(seed, x.values.begin(), x.values.end());
|
||||
return seed;
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
#endif
|
96
test/hash_fwd_test_1.cpp
Normal file
96
test/hash_fwd_test_1.cpp
Normal file
@ -0,0 +1,96 @@
|
||||
|
||||
// Copyright 2006-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)
|
||||
|
||||
// This checks that template code implemented using hash_fwd will work.
|
||||
|
||||
#include "./config.hpp"
|
||||
|
||||
#include "./hash_fwd_test.hpp"
|
||||
|
||||
#include <boost/core/lightweight_test.hpp>
|
||||
|
||||
#if defined(BOOST_HASH_TEST_EXTENSIONS) && !defined(BOOST_HASH_TEST_STD_INCLUDES)
|
||||
|
||||
#include <boost/container_hash/hash.hpp>
|
||||
#include <string>
|
||||
|
||||
void fwd_test1()
|
||||
{
|
||||
test::test_type1<int> x(5);
|
||||
test::test_type1<std::string> y("Test");
|
||||
|
||||
BOOST_HASH_TEST_NAMESPACE::hash<int> hasher_int;
|
||||
BOOST_HASH_TEST_NAMESPACE::hash<std::string> hasher_string;
|
||||
BOOST_HASH_TEST_NAMESPACE::hash<test::test_type1<int> > hasher_test_int;
|
||||
BOOST_HASH_TEST_NAMESPACE::hash<test::test_type1<std::string> > hasher_test_string;
|
||||
|
||||
BOOST_TEST(hasher_int(5) == hasher_test_int(x));
|
||||
BOOST_TEST(hasher_string("Test") == hasher_test_string(y));
|
||||
}
|
||||
|
||||
void fwd_test2()
|
||||
{
|
||||
test::test_type2<int> x(5, 10);
|
||||
test::test_type2<std::string> y("Test1", "Test2");
|
||||
|
||||
std::size_t seed1 = 0;
|
||||
BOOST_HASH_TEST_NAMESPACE::hash_combine(seed1, 5);
|
||||
BOOST_HASH_TEST_NAMESPACE::hash_combine(seed1, 10);
|
||||
|
||||
std::size_t seed2 = 0;
|
||||
BOOST_HASH_TEST_NAMESPACE::hash_combine(seed2, std::string("Test1"));
|
||||
BOOST_HASH_TEST_NAMESPACE::hash_combine(seed2, std::string("Test2"));
|
||||
|
||||
BOOST_HASH_TEST_NAMESPACE::hash<test::test_type2<int> > hasher_test_int;
|
||||
BOOST_HASH_TEST_NAMESPACE::hash<test::test_type2<std::string> > hasher_test_string;
|
||||
|
||||
BOOST_TEST(seed1 == hasher_test_int(x));
|
||||
BOOST_TEST(seed2 == hasher_test_string(y));
|
||||
}
|
||||
|
||||
void fwd_test3()
|
||||
{
|
||||
std::vector<int> values1;
|
||||
values1.push_back(10);
|
||||
values1.push_back(15);
|
||||
values1.push_back(20);
|
||||
values1.push_back(3);
|
||||
|
||||
std::vector<std::string> values2;
|
||||
values2.push_back("Chico");
|
||||
values2.push_back("Groucho");
|
||||
values2.push_back("Harpo");
|
||||
values2.push_back("Gummo");
|
||||
values2.push_back("Zeppo");
|
||||
|
||||
test::test_type3<int> x(values1.begin(), values1.end());
|
||||
test::test_type3<std::string> y(values2.begin(), values2.end());
|
||||
|
||||
std::size_t seed1 =
|
||||
BOOST_HASH_TEST_NAMESPACE::hash_range(values1.begin(), values1.end());
|
||||
BOOST_HASH_TEST_NAMESPACE::hash_range(seed1, values1.begin(), values1.end());
|
||||
|
||||
std::size_t seed2 =
|
||||
BOOST_HASH_TEST_NAMESPACE::hash_range(values2.begin(), values2.end());
|
||||
BOOST_HASH_TEST_NAMESPACE::hash_range(seed2, values2.begin(), values2.end());
|
||||
|
||||
BOOST_HASH_TEST_NAMESPACE::hash<test::test_type3<int> > hasher_test_int;
|
||||
BOOST_HASH_TEST_NAMESPACE::hash<test::test_type3<std::string> > hasher_test_string;
|
||||
|
||||
BOOST_TEST(seed1 == hasher_test_int(x));
|
||||
BOOST_TEST(seed2 == hasher_test_string(y));
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
int main()
|
||||
{
|
||||
#ifdef BOOST_HASH_TEST_EXTENSIONS
|
||||
fwd_test1();
|
||||
fwd_test2();
|
||||
fwd_test3();
|
||||
#endif
|
||||
return boost::report_errors();
|
||||
}
|
47
test/hash_fwd_test_2.cpp
Normal file
47
test/hash_fwd_test_2.cpp
Normal file
@ -0,0 +1,47 @@
|
||||
|
||||
// Copyright 2006-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)
|
||||
|
||||
// This test just makes sure a header which uses hash_fwd can compile without
|
||||
// the main hash headers.
|
||||
|
||||
#include "./config.hpp"
|
||||
|
||||
#if !defined(BOOST_HASH_TEST_EXTENSIONS) || defined(BOOST_HASH_TEST_STD_INCLUDES)
|
||||
|
||||
int main() {}
|
||||
|
||||
#else
|
||||
|
||||
#include "./hash_fwd_test.hpp"
|
||||
#include <boost/core/lightweight_test.hpp>
|
||||
|
||||
template <class T> void unused(T const&) {}
|
||||
|
||||
void fwd_test()
|
||||
{
|
||||
test::test_type1<int> x1(3);
|
||||
test::test_type1<std::string> y1("Black");
|
||||
test::test_type2<int> x2(25, 16);
|
||||
test::test_type2<std::string> y2("White", "Green");
|
||||
|
||||
std::vector<int> empty;
|
||||
std::vector<std::string> empty2;
|
||||
|
||||
test::test_type3<int> x3(empty.begin(), empty.end());
|
||||
test::test_type3<std::string> y3(empty2.begin(), empty2.end());
|
||||
|
||||
// Prevent gcc warnings:
|
||||
unused(x1); unused(x2); unused(x3);
|
||||
unused(y1); unused(y2); unused(y3);
|
||||
}
|
||||
|
||||
int main()
|
||||
{
|
||||
fwd_test();
|
||||
|
||||
return boost::report_errors();
|
||||
}
|
||||
|
||||
#endif // defined(BOOST_HASH_TEST_EXTENSIONS) && !defined(BOOST_HASH_TEST_STD_INCLUDES)
|
103
test/hash_global_namespace_test.cpp
Normal file
103
test/hash_global_namespace_test.cpp
Normal file
@ -0,0 +1,103 @@
|
||||
|
||||
// Copyright 2006-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)
|
||||
|
||||
// This test demonstrates an ADL bug in Borland 5.5 where ADL isn't performed
|
||||
// in the global namespace.
|
||||
|
||||
#include "./config.hpp"
|
||||
|
||||
#include <boost/config.hpp>
|
||||
#include <cstddef>
|
||||
|
||||
struct custom
|
||||
{
|
||||
int value_;
|
||||
|
||||
std::size_t hash() const
|
||||
{
|
||||
return static_cast<std::size_t>(value_ * 10);
|
||||
}
|
||||
|
||||
#if !defined(BOOST_NO_ARGUMENT_DEPENDENT_LOOKUP)
|
||||
friend std::size_t hash_value(custom const& x )
|
||||
{
|
||||
return x.hash();
|
||||
}
|
||||
#endif
|
||||
|
||||
custom(int x) : value_(x) {}
|
||||
};
|
||||
|
||||
#if defined(BOOST_NO_ARGUMENT_DEPENDENT_LOOKUP)
|
||||
namespace boost
|
||||
{
|
||||
std::size_t hash_value(custom x)
|
||||
{
|
||||
return x.hash();
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
#include "./config.hpp"
|
||||
|
||||
#ifdef BOOST_HASH_TEST_EXTENSIONS
|
||||
# ifdef BOOST_HASH_TEST_STD_INCLUDES
|
||||
# include <functional>
|
||||
# else
|
||||
# include <boost/container_hash/hash.hpp>
|
||||
# endif
|
||||
#endif
|
||||
|
||||
#include <boost/core/lightweight_test.hpp>
|
||||
|
||||
#ifdef BOOST_HASH_TEST_EXTENSIONS
|
||||
|
||||
#include <vector>
|
||||
#include <string>
|
||||
#include <cctype>
|
||||
|
||||
void custom_tests()
|
||||
{
|
||||
BOOST_HASH_TEST_NAMESPACE::hash<custom> custom_hasher;
|
||||
BOOST_TEST(custom_hasher(10) == 100u);
|
||||
custom x(55);
|
||||
BOOST_TEST(custom_hasher(x) == 550u);
|
||||
|
||||
{
|
||||
using namespace BOOST_HASH_TEST_NAMESPACE;
|
||||
BOOST_TEST(custom_hasher(x) == hash_value(x));
|
||||
}
|
||||
|
||||
std::vector<custom> custom_vector;
|
||||
custom_vector.push_back(5);
|
||||
custom_vector.push_back(25);
|
||||
custom_vector.push_back(35);
|
||||
|
||||
std::size_t seed = 0;
|
||||
BOOST_HASH_TEST_NAMESPACE::hash_combine(seed, custom(5));
|
||||
BOOST_HASH_TEST_NAMESPACE::hash_combine(seed, custom(25));
|
||||
BOOST_HASH_TEST_NAMESPACE::hash_combine(seed, custom(35));
|
||||
|
||||
std::size_t seed2 = 0;
|
||||
BOOST_HASH_TEST_NAMESPACE::hash_combine(seed2, 50u);
|
||||
BOOST_HASH_TEST_NAMESPACE::hash_combine(seed2, 250u);
|
||||
BOOST_HASH_TEST_NAMESPACE::hash_combine(seed2, 350u);
|
||||
|
||||
BOOST_TEST(seed == BOOST_HASH_TEST_NAMESPACE::hash_range(
|
||||
custom_vector.begin(), custom_vector.end()));
|
||||
BOOST_TEST(seed == seed2);
|
||||
}
|
||||
|
||||
#endif // BOOST_HASH_TEST_EXTENSIONS
|
||||
|
||||
|
||||
int main()
|
||||
{
|
||||
#ifdef BOOST_HASH_TEST_EXTENSIONS
|
||||
custom_tests();
|
||||
#endif
|
||||
return boost::report_errors();
|
||||
}
|
||||
|
124
test/hash_info.cpp
Normal file
124
test/hash_info.cpp
Normal file
@ -0,0 +1,124 @@
|
||||
|
||||
// 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>
|
||||
#include <limits>
|
||||
#include <climits>
|
||||
|
||||
#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.1x, VS2017"},
|
||||
{1920, "Visual C++ 14.2x, VS2019"},
|
||||
{1930, "Visual C++ 14.3x, VS2022"},
|
||||
};
|
||||
|
||||
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
|
||||
|
||||
#define PRINT(x) std::cout << #x ": " << x << std::endl
|
||||
|
||||
int main() {
|
||||
write_compiler_info();
|
||||
std::cout << std::endl;
|
||||
|
||||
PRINT(__cplusplus);
|
||||
PRINT(BOOST_CXX_VERSION);
|
||||
std::cout << std::endl;
|
||||
|
||||
#if defined(BOOST_NO_CXX17_HDR_STRING_VIEW)
|
||||
std::cout << "No <string_view>" << std::endl;
|
||||
#else
|
||||
std::cout << "Has <string_view>" << std::endl;
|
||||
#endif
|
||||
|
||||
#if defined(BOOST_NO_CXX17_HDR_OPTIONAL)
|
||||
std::cout << "No <optional>" << std::endl;
|
||||
#else
|
||||
std::cout << "Has <optional>" << std::endl;
|
||||
#endif
|
||||
|
||||
#if defined(BOOST_NO_CXX17_HDR_VARIANT)
|
||||
std::cout << "No <variant>" << std::endl;
|
||||
#else
|
||||
std::cout << "Has <variant>" << std::endl;
|
||||
#endif
|
||||
|
||||
#if defined(BOOST_NO_CXX11_HDR_TYPEINDEX)
|
||||
std::cout << "No <typeindex>" << std::endl;
|
||||
#else
|
||||
std::cout << "Has <typeindex>" << std::endl;
|
||||
#endif
|
||||
|
||||
#if defined(BOOST_NO_CXX11_HDR_SYSTEM_ERROR)
|
||||
std::cout << "No <system_error>" << std::endl;
|
||||
#else
|
||||
std::cout << "Has <system_error>" << std::endl;
|
||||
#endif
|
||||
|
||||
std::cout << std::endl;
|
||||
|
||||
PRINT(CHAR_BIT);
|
||||
std::cout << std::endl;
|
||||
|
||||
PRINT(sizeof(std::size_t)*CHAR_BIT);
|
||||
std::cout << std::endl;
|
||||
|
||||
PRINT(sizeof(float)*CHAR_BIT);
|
||||
PRINT(std::numeric_limits<float>::digits);
|
||||
std::cout << std::endl;
|
||||
|
||||
PRINT(sizeof(double)*CHAR_BIT);
|
||||
PRINT(std::numeric_limits<double>::digits);
|
||||
std::cout << std::endl;
|
||||
|
||||
PRINT(sizeof(long double)*CHAR_BIT);
|
||||
PRINT(std::numeric_limits<long double>::digits);
|
||||
}
|
75
test/hash_integral_test.cpp
Normal file
75
test/hash_integral_test.cpp
Normal file
@ -0,0 +1,75 @@
|
||||
// Copyright 2005-2009 Daniel James.
|
||||
// Copyright 2021 Peter Dimov.
|
||||
// Distributed under the Boost Software License, Version 1.0.
|
||||
// https://www.boost.org/LICENSE_1_0.txt
|
||||
|
||||
#include <boost/container_hash/hash.hpp>
|
||||
#include <boost/core/lightweight_test.hpp>
|
||||
#include <boost/core/type_name.hpp>
|
||||
#include <boost/type_traits/is_signed.hpp>
|
||||
#include <set>
|
||||
|
||||
#if defined(BOOST_MSVC)
|
||||
#pragma warning(disable: 4127) // conditional expression is constant
|
||||
#endif
|
||||
|
||||
// This test checks that small numbers hash to themselves even if
|
||||
// their type is wider than size_t
|
||||
|
||||
template<class T>
|
||||
void identity_test()
|
||||
{
|
||||
if( boost::is_signed<T>::value )
|
||||
{
|
||||
for( int i = -128; i <= 127; ++i )
|
||||
{
|
||||
BOOST_TEST_EQ( boost::hash<T>()( static_cast<T>( i ) ), static_cast<std::size_t>( i ) );
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
for( int i = 0; i <= 255; ++i )
|
||||
{
|
||||
BOOST_TEST_EQ( boost::hash<T>()( static_cast<T>( i ) ), static_cast<std::size_t>( i ) );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#define TEST(type) std::cerr << "Testing: " #type " (" << boost::core::type_name<type>() << ")\n"; identity_test<type>();
|
||||
|
||||
int main()
|
||||
{
|
||||
TEST(char)
|
||||
TEST(signed char)
|
||||
TEST(unsigned char)
|
||||
#ifndef BOOST_NO_INTRINSIC_WCHAR_T
|
||||
TEST(wchar_t)
|
||||
#endif
|
||||
#ifndef BOOST_NO_CXX11_CHAR16_T
|
||||
TEST(char16_t)
|
||||
#endif
|
||||
#ifndef BOOST_NO_CXX11_CHAR32_T
|
||||
TEST(char32_t)
|
||||
#endif
|
||||
TEST(short)
|
||||
TEST(unsigned short)
|
||||
TEST(int)
|
||||
TEST(unsigned int)
|
||||
TEST(long)
|
||||
TEST(unsigned long)
|
||||
|
||||
#if !defined(BOOST_NO_LONG_LONG)
|
||||
TEST(boost::long_long_type)
|
||||
TEST(boost::ulong_long_type)
|
||||
#endif
|
||||
|
||||
#if defined(BOOST_HAS_INT128)
|
||||
TEST(boost::int128_type)
|
||||
TEST(boost::uint128_type)
|
||||
#endif
|
||||
|
||||
TEST(std::size_t)
|
||||
TEST(std::ptrdiff_t)
|
||||
|
||||
return boost::report_errors();
|
||||
}
|
35
test/hash_list_test.cpp
Normal file
35
test/hash_list_test.cpp
Normal file
@ -0,0 +1,35 @@
|
||||
|
||||
// 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)
|
||||
|
||||
#include "./config.hpp"
|
||||
|
||||
#ifdef BOOST_HASH_TEST_EXTENSIONS
|
||||
# ifdef BOOST_HASH_TEST_STD_INCLUDES
|
||||
# include <functional>
|
||||
# else
|
||||
# include <boost/container_hash/hash.hpp>
|
||||
# endif
|
||||
#endif
|
||||
|
||||
#include <boost/core/lightweight_test.hpp>
|
||||
|
||||
#ifdef BOOST_HASH_TEST_EXTENSIONS
|
||||
|
||||
#include <list>
|
||||
|
||||
using std::list;
|
||||
#define CONTAINER_TYPE list
|
||||
#include "./hash_sequence_test.hpp"
|
||||
|
||||
#endif // BOOST_HASH_TEST_EXTENSIONS
|
||||
|
||||
int main()
|
||||
{
|
||||
#ifdef BOOST_HASH_TEST_EXTENSIONS
|
||||
list_tests::list_hash_integer_tests();
|
||||
#endif
|
||||
|
||||
return boost::report_errors();
|
||||
}
|
17
test/hash_long_double_test.cpp
Normal file
17
test/hash_long_double_test.cpp
Normal file
@ -0,0 +1,17 @@
|
||||
|
||||
// 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)
|
||||
|
||||
#include "hash_float_test.hpp"
|
||||
|
||||
int main()
|
||||
{
|
||||
std::cerr<<"Compiler: "<<BOOST_COMPILER<<"\n";
|
||||
std::cerr<<"Platform: "<<BOOST_PLATFORM<<"\n";
|
||||
std::cerr<<"Library: "<<BOOST_STDLIB<<"\n\n";
|
||||
|
||||
float_tests("long double", (long double*) 0);
|
||||
|
||||
return boost::report_errors();
|
||||
}
|
40
test/hash_map_test.cpp
Normal file
40
test/hash_map_test.cpp
Normal file
@ -0,0 +1,40 @@
|
||||
|
||||
// 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)
|
||||
|
||||
#include "./config.hpp"
|
||||
|
||||
#ifdef BOOST_HASH_TEST_EXTENSIONS
|
||||
# ifdef BOOST_HASH_TEST_STD_INCLUDES
|
||||
# include <functional>
|
||||
# else
|
||||
# include <boost/container_hash/hash.hpp>
|
||||
# endif
|
||||
#endif
|
||||
|
||||
#include <boost/core/lightweight_test.hpp>
|
||||
|
||||
#include <map>
|
||||
|
||||
#ifdef BOOST_HASH_TEST_EXTENSIONS
|
||||
|
||||
using std::map;
|
||||
#define CONTAINER_TYPE map
|
||||
#include "./hash_map_test.hpp"
|
||||
|
||||
using std::multimap;
|
||||
#define CONTAINER_TYPE multimap
|
||||
#include "./hash_map_test.hpp"
|
||||
|
||||
#endif // BOOST_HASH_TEST_EXTENSIONS
|
||||
|
||||
int main()
|
||||
{
|
||||
#ifdef BOOST_HASH_TEST_EXTENSIONS
|
||||
map_tests::map_hash_integer_tests();
|
||||
multimap_tests::multimap_hash_integer_tests();
|
||||
#endif
|
||||
|
||||
return boost::report_errors();
|
||||
}
|
83
test/hash_map_test.hpp
Normal file
83
test/hash_map_test.hpp
Normal file
@ -0,0 +1,83 @@
|
||||
|
||||
// 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)
|
||||
|
||||
#if !defined(CONTAINER_TYPE)
|
||||
#error "CONTAINER_TYPE not defined"
|
||||
#else
|
||||
|
||||
#if defined(BOOST_MSVC)
|
||||
#pragma warning(push)
|
||||
#pragma warning(disable:4244) // conversion from 'int' to 'float'
|
||||
#pragma warning(disable:4245) // signed/unsigned mismatch
|
||||
#endif
|
||||
|
||||
#if defined(__GNUC__) && __GNUC__ == 8
|
||||
# pragma GCC diagnostic push
|
||||
# pragma GCC diagnostic ignored "-Wsign-conversion"
|
||||
#endif
|
||||
|
||||
namespace HASH_TEST_CAT(CONTAINER_TYPE, _tests)
|
||||
{
|
||||
template <class T>
|
||||
void integer_tests(T* = 0)
|
||||
{
|
||||
const int number_of_containers = 10;
|
||||
T containers[number_of_containers];
|
||||
typedef BOOST_DEDUCED_TYPENAME T::value_type pair;
|
||||
typedef BOOST_DEDUCED_TYPENAME T::key_type key;
|
||||
typedef BOOST_DEDUCED_TYPENAME T::mapped_type value;
|
||||
|
||||
for(int i = 0; i < 5; ++i) {
|
||||
for(int j = 0; j < i; ++j)
|
||||
containers[i].insert(pair(key(0), value(0)));
|
||||
}
|
||||
|
||||
containers[6].insert(pair(key(1),value(0)));
|
||||
containers[7].insert(pair(key(1),value(0)));
|
||||
containers[7].insert(pair(key(1),value(0)));
|
||||
containers[8].insert(pair(key(-1),value(1)));
|
||||
containers[9].insert(pair(key(-1),value(3)));
|
||||
containers[9].insert(pair(key(-1),value(3)));
|
||||
|
||||
BOOST_HASH_TEST_NAMESPACE::hash<T> hasher;
|
||||
|
||||
for(int i2 = 0; i2 < number_of_containers; ++i2) {
|
||||
BOOST_TEST(hasher(containers[i2]) == hasher(containers[i2]));
|
||||
|
||||
BOOST_TEST(hasher(containers[i2]) ==
|
||||
BOOST_HASH_TEST_NAMESPACE::hash_value(containers[i2]));
|
||||
|
||||
BOOST_TEST(hasher(containers[i2])
|
||||
== BOOST_HASH_TEST_NAMESPACE::hash_range(
|
||||
containers[i2].begin(), containers[i2].end()));
|
||||
|
||||
for(int j2 = i2 + 1; j2 < number_of_containers; ++j2) {
|
||||
BOOST_TEST(
|
||||
(containers[i2] == containers[j2]) ==
|
||||
(hasher(containers[i2]) == hasher(containers[j2]))
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void HASH_TEST_CAT(CONTAINER_TYPE, _hash_integer_tests())
|
||||
{
|
||||
integer_tests((CONTAINER_TYPE<char, unsigned char>*) 0);
|
||||
integer_tests((CONTAINER_TYPE<int, float>*) 0);
|
||||
integer_tests((CONTAINER_TYPE<unsigned long, unsigned long>*) 0);
|
||||
integer_tests((CONTAINER_TYPE<double, short>*) 0);
|
||||
}
|
||||
}
|
||||
|
||||
#if defined(__GNUC__) && __GNUC__ == 8
|
||||
# pragma GCC diagnostic pop
|
||||
#endif
|
||||
|
||||
#if defined(BOOST_MSVC)
|
||||
#pragma warning(pop)
|
||||
#endif
|
||||
|
||||
#undef CONTAINER_TYPE
|
||||
#endif
|
37
test/hash_no_ext_macro_1.cpp
Normal file
37
test/hash_no_ext_macro_1.cpp
Normal file
@ -0,0 +1,37 @@
|
||||
|
||||
// Copyright 2006-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)
|
||||
|
||||
#include "./config.hpp"
|
||||
|
||||
#if defined(BOOST_HASH_TEST_EXTENSIONS)
|
||||
|
||||
// Include header without BOOST_HASH_NO_EXTENSIONS defined
|
||||
# if defined(BOOST_HASH_NO_EXTENSIONS)
|
||||
# undef BOOST_HASH_NO_EXTENSIONS
|
||||
# endif
|
||||
# include <boost/container_hash/hash.hpp>
|
||||
|
||||
// Include header with BOOST_HASH_NO_EXTENSIONS defined
|
||||
# define BOOST_HASH_NO_EXTENSIONS
|
||||
# include <boost/container_hash/hash.hpp>
|
||||
#endif
|
||||
|
||||
#include <boost/core/lightweight_test.hpp>
|
||||
#include <deque>
|
||||
|
||||
int main()
|
||||
{
|
||||
#if defined(BOOST_HASH_TEST_EXTENSIONS)
|
||||
std::deque<int> x;
|
||||
|
||||
x.push_back(1);
|
||||
x.push_back(2);
|
||||
|
||||
BOOST_HASH_TEST_NAMESPACE::hash<std::deque<int> > hasher;
|
||||
BOOST_TEST(hasher(x) == BOOST_HASH_TEST_NAMESPACE::hash_value(x));
|
||||
#endif
|
||||
|
||||
return boost::report_errors();
|
||||
}
|
37
test/hash_no_ext_macro_2.cpp
Normal file
37
test/hash_no_ext_macro_2.cpp
Normal file
@ -0,0 +1,37 @@
|
||||
|
||||
// Copyright 2006-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)
|
||||
|
||||
#include "./config.hpp"
|
||||
|
||||
#if defined(BOOST_HASH_TEST_EXTENSIONS)
|
||||
|
||||
// Include header with BOOST_HASH_NO_EXTENSIONS defined
|
||||
# if !defined(BOOST_HASH_NO_EXTENSIONS)
|
||||
# define BOOST_HASH_NO_EXTENSIONS
|
||||
# endif
|
||||
# include <boost/container_hash/hash.hpp>
|
||||
|
||||
// Include header without BOOST_HASH_NO_EXTENSIONS defined
|
||||
# undef BOOST_HASH_NO_EXTENSIONS
|
||||
# include <boost/container_hash/hash.hpp>
|
||||
#endif
|
||||
|
||||
#include <boost/core/lightweight_test.hpp>
|
||||
#include <map>
|
||||
|
||||
int main()
|
||||
{
|
||||
#if defined(BOOST_HASH_TEST_EXTENSIONS)
|
||||
std::map<int, int> x;
|
||||
|
||||
x.insert(std::map<int, int>::value_type(53, -42));
|
||||
x.insert(std::map<int, int>::value_type(14, -75));
|
||||
|
||||
BOOST_HASH_TEST_NAMESPACE::hash<std::map<int, int> > hasher;
|
||||
BOOST_TEST(hasher(x) == BOOST_HASH_TEST_NAMESPACE::hash_value(x));
|
||||
#endif
|
||||
|
||||
return boost::report_errors();
|
||||
}
|
201
test/hash_number_test.cpp
Normal file
201
test/hash_number_test.cpp
Normal file
@ -0,0 +1,201 @@
|
||||
|
||||
// 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)
|
||||
|
||||
#include "./config.hpp"
|
||||
|
||||
#ifdef BOOST_HASH_TEST_STD_INCLUDES
|
||||
# include <functional>
|
||||
#else
|
||||
# include <boost/container_hash/hash.hpp>
|
||||
#endif
|
||||
|
||||
#include <iostream>
|
||||
#include <boost/core/lightweight_test.hpp>
|
||||
|
||||
#include <boost/container_hash/detail/limits.hpp>
|
||||
#include <boost/core/enable_if.hpp>
|
||||
|
||||
#include "./compile_time.hpp"
|
||||
|
||||
#if defined(BOOST_MSVC)
|
||||
#pragma warning(push)
|
||||
#pragma warning(disable:4127) // conditional expression is constant
|
||||
#pragma warning(disable:4309) // truncation of constant value
|
||||
#pragma warning(disable:4310) // cast truncates constant value
|
||||
#endif
|
||||
|
||||
#if ( defined(__GNUC__) || defined(__clang__) ) && !defined(BOOST_INTEL_CXX_VERSION)
|
||||
#pragma GCC diagnostic ignored "-Wfloat-equal"
|
||||
#endif
|
||||
|
||||
template <class T>
|
||||
void numeric_extra_tests(typename
|
||||
boost::enable_if_c<boost::hash_detail::limits<T>::is_integer,
|
||||
void*>::type = 0)
|
||||
{
|
||||
typedef boost::hash_detail::limits<T> limits;
|
||||
|
||||
if(limits::is_signed ||
|
||||
limits::digits <= boost::hash_detail::limits<std::size_t>::digits)
|
||||
{
|
||||
BOOST_TEST(BOOST_HASH_TEST_NAMESPACE::hash_value(T(-5)) == (std::size_t)T(-5));
|
||||
}
|
||||
BOOST_TEST(BOOST_HASH_TEST_NAMESPACE::hash_value(T(0)) == (std::size_t)T(0u));
|
||||
BOOST_TEST(BOOST_HASH_TEST_NAMESPACE::hash_value(T(10)) == (std::size_t)T(10u));
|
||||
BOOST_TEST(BOOST_HASH_TEST_NAMESPACE::hash_value(T(25)) == (std::size_t)T(25u));
|
||||
}
|
||||
|
||||
template <class T>
|
||||
void numeric_extra_tests(typename
|
||||
boost::disable_if_c<boost::hash_detail::limits<T>::is_integer,
|
||||
void*>::type = 0)
|
||||
{
|
||||
}
|
||||
|
||||
template <class T>
|
||||
void numeric_test(T*)
|
||||
{
|
||||
compile_time_tests((T*) 0);
|
||||
|
||||
BOOST_HASH_TEST_NAMESPACE::hash<T> x1;
|
||||
BOOST_HASH_TEST_NAMESPACE::hash<T> x2;
|
||||
|
||||
T v1 = (T) -5;
|
||||
BOOST_TEST(x1(v1) == x2(v1));
|
||||
BOOST_TEST(x1(T(-5)) == x2(T(-5)));
|
||||
BOOST_TEST(x1(T(0)) == x2(T(0)));
|
||||
BOOST_TEST(x1(T(10)) == x2(T(10)));
|
||||
BOOST_TEST(x1(T(25)) == x2(T(25)));
|
||||
BOOST_TEST(x1(T(5) - T(5)) == x2(T(0)));
|
||||
BOOST_TEST(x1(T(6) + T(4)) == x2(T(10)));
|
||||
|
||||
#if defined(BOOST_HASH_TEST_EXTENSIONS)
|
||||
BOOST_TEST(x1(T(-5)) == BOOST_HASH_TEST_NAMESPACE::hash_value(T(-5)));
|
||||
BOOST_TEST(x1(T(0)) == BOOST_HASH_TEST_NAMESPACE::hash_value(T(0)));
|
||||
BOOST_TEST(x1(T(10)) == BOOST_HASH_TEST_NAMESPACE::hash_value(T(10)));
|
||||
BOOST_TEST(x1(T(25)) == BOOST_HASH_TEST_NAMESPACE::hash_value(T(25)));
|
||||
|
||||
numeric_extra_tests<T>();
|
||||
#endif
|
||||
}
|
||||
|
||||
template <class T>
|
||||
void limits_test(T*)
|
||||
{
|
||||
typedef boost::hash_detail::limits<T> limits;
|
||||
|
||||
if(limits::is_specialized)
|
||||
{
|
||||
BOOST_HASH_TEST_NAMESPACE::hash<T> x1;
|
||||
BOOST_HASH_TEST_NAMESPACE::hash<T> x2;
|
||||
|
||||
T min_value = (limits::min)();
|
||||
T max_value = (limits::max)();
|
||||
|
||||
BOOST_TEST(x1(min_value) == x2((limits::min)()));
|
||||
BOOST_TEST(x1(max_value) == x2((limits::max)()));
|
||||
|
||||
#if defined(BOOST_HASH_TEST_EXTENSIONS)
|
||||
BOOST_TEST(x1(min_value) == BOOST_HASH_TEST_NAMESPACE::hash_value(min_value));
|
||||
BOOST_TEST(x1(max_value) == BOOST_HASH_TEST_NAMESPACE::hash_value(max_value));
|
||||
|
||||
if (limits::is_integer)
|
||||
{
|
||||
BOOST_TEST_EQ(BOOST_HASH_TEST_NAMESPACE::hash_value(min_value), std::size_t(min_value));
|
||||
BOOST_TEST_EQ(BOOST_HASH_TEST_NAMESPACE::hash_value(max_value), std::size_t(max_value));
|
||||
}
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
template <class T>
|
||||
void poor_quality_tests(T*)
|
||||
{
|
||||
typedef boost::hash_detail::limits<T> limits;
|
||||
|
||||
BOOST_HASH_TEST_NAMESPACE::hash<T> x1;
|
||||
BOOST_HASH_TEST_NAMESPACE::hash<T> x2;
|
||||
|
||||
// A hash function can legally fail these tests, but it'll not be a good
|
||||
// sign.
|
||||
if(T(1) != T(-1))
|
||||
BOOST_TEST(x1(T(1)) != x2(T(-1)));
|
||||
if(T(1) != T(2))
|
||||
BOOST_TEST(x1(T(1)) != x2(T(2)));
|
||||
|
||||
// TODO: This test is useless for floating point numbers.
|
||||
T max_number = static_cast<T>((limits::max)());
|
||||
T max_minus_one = static_cast<T>(max_number - 1);
|
||||
if (max_number != max_minus_one) {
|
||||
BOOST_TEST(x1(max_number) != x1(max_minus_one));
|
||||
}
|
||||
}
|
||||
|
||||
void bool_test()
|
||||
{
|
||||
BOOST_HASH_TEST_NAMESPACE::hash<bool> x1;
|
||||
BOOST_HASH_TEST_NAMESPACE::hash<bool> x2;
|
||||
|
||||
BOOST_TEST(x1(true) == x2(true));
|
||||
BOOST_TEST(x1(false) == x2(false));
|
||||
BOOST_TEST(x1(true) != x2(false));
|
||||
BOOST_TEST(x1(false) != x2(true));
|
||||
}
|
||||
|
||||
#define NUMERIC_TEST(type, name) \
|
||||
std::cerr<<"Testing: " BOOST_STRINGIZE(name) "\n"; \
|
||||
numeric_test((type*) 0); \
|
||||
limits_test((type*) 0); \
|
||||
poor_quality_tests((type*) 0);
|
||||
#define NUMERIC_TEST_NO_LIMITS(type, name) \
|
||||
std::cerr<<"Testing: " BOOST_STRINGIZE(name) "\n"; \
|
||||
numeric_test((type*) 0); \
|
||||
poor_quality_tests((type*) 0);
|
||||
|
||||
int main()
|
||||
{
|
||||
NUMERIC_TEST(char, char)
|
||||
NUMERIC_TEST(signed char, schar)
|
||||
NUMERIC_TEST(unsigned char, uchar)
|
||||
#ifndef BOOST_NO_INTRINSIC_WCHAR_T
|
||||
NUMERIC_TEST(wchar_t, wchar)
|
||||
#endif
|
||||
#ifndef BOOST_NO_CXX11_CHAR16_T
|
||||
NUMERIC_TEST(char16_t, char16)
|
||||
#endif
|
||||
#ifndef BOOST_NO_CXX11_CHAR32_T
|
||||
NUMERIC_TEST(char32_t, char32)
|
||||
#endif
|
||||
NUMERIC_TEST(short, short)
|
||||
NUMERIC_TEST(unsigned short, ushort)
|
||||
NUMERIC_TEST(int, int)
|
||||
NUMERIC_TEST(unsigned int, uint)
|
||||
NUMERIC_TEST(long, hash_long)
|
||||
NUMERIC_TEST(unsigned long, ulong)
|
||||
|
||||
#if !defined(BOOST_NO_LONG_LONG)
|
||||
NUMERIC_TEST_NO_LIMITS(boost::long_long_type, long_long)
|
||||
NUMERIC_TEST_NO_LIMITS(boost::ulong_long_type, ulong_long)
|
||||
#endif
|
||||
|
||||
#if defined(BOOST_HAS_INT128)
|
||||
NUMERIC_TEST_NO_LIMITS(boost::int128_type, int128)
|
||||
NUMERIC_TEST_NO_LIMITS(boost::uint128_type, uint128)
|
||||
#endif
|
||||
|
||||
NUMERIC_TEST(float, float)
|
||||
NUMERIC_TEST(double, double)
|
||||
|
||||
NUMERIC_TEST(std::size_t, size_t)
|
||||
NUMERIC_TEST(std::ptrdiff_t, ptrdiff_t)
|
||||
|
||||
bool_test();
|
||||
|
||||
return boost::report_errors();
|
||||
}
|
||||
|
||||
#if defined(BOOST_MSVC)
|
||||
#pragma warning(pop)
|
||||
#endif
|
90
test/hash_number_test2.cpp
Normal file
90
test/hash_number_test2.cpp
Normal file
@ -0,0 +1,90 @@
|
||||
// Copyright 2005-2009 Daniel James.
|
||||
// Copyright 2021 Peter Dimov.
|
||||
// Distributed under the Boost Software License, Version 1.0.
|
||||
// https://www.boost.org/LICENSE_1_0.txt
|
||||
|
||||
#include <boost/container_hash/hash.hpp>
|
||||
#include <boost/core/lightweight_test.hpp>
|
||||
#include <boost/core/type_name.hpp>
|
||||
#include <set>
|
||||
|
||||
#if defined(BOOST_MSVC)
|
||||
# pragma warning(disable: 4244) // conversion from int to float
|
||||
#endif
|
||||
|
||||
#if defined(__GNUC__) || defined(__clang__)
|
||||
# pragma GCC diagnostic ignored "-Wconversion"
|
||||
# pragma GCC diagnostic ignored "-Wsign-conversion"
|
||||
#endif
|
||||
|
||||
// This test checks for collisions in a small range of numbers
|
||||
|
||||
template<class T, int M>
|
||||
void collision_test_()
|
||||
{
|
||||
std::set<std::size_t> hashes;
|
||||
|
||||
for( int i = -128; i <= 127; ++i )
|
||||
{
|
||||
hashes.insert( boost::hash<T>()( i * M ) );
|
||||
}
|
||||
|
||||
BOOST_TEST_EQ( hashes.size(), 256u );
|
||||
}
|
||||
|
||||
template <class T>
|
||||
void collision_test()
|
||||
{
|
||||
collision_test_<T, 1>();
|
||||
collision_test_<T, 2>();
|
||||
collision_test_<T, 3>();
|
||||
collision_test_<T, 4>();
|
||||
collision_test_<T, 5>();
|
||||
collision_test_<T, 8>();
|
||||
collision_test_<T, 10>();
|
||||
collision_test_<T, 16>();
|
||||
collision_test_<T, 32>();
|
||||
collision_test_<T, 64>();
|
||||
collision_test_<T, 100>();
|
||||
collision_test_<T, 128>();
|
||||
}
|
||||
|
||||
#define TEST(type) std::cerr << "Testing: " #type " (" << boost::core::type_name<type>() << ")\n"; collision_test<type>();
|
||||
|
||||
int main()
|
||||
{
|
||||
#ifndef BOOST_NO_INTRINSIC_WCHAR_T
|
||||
TEST(wchar_t)
|
||||
#endif
|
||||
#ifndef BOOST_NO_CXX11_CHAR16_T
|
||||
TEST(char16_t)
|
||||
#endif
|
||||
#ifndef BOOST_NO_CXX11_CHAR32_T
|
||||
TEST(char32_t)
|
||||
#endif
|
||||
TEST(short)
|
||||
TEST(unsigned short)
|
||||
TEST(int)
|
||||
TEST(unsigned int)
|
||||
TEST(long)
|
||||
TEST(unsigned long)
|
||||
|
||||
#if !defined(BOOST_NO_LONG_LONG)
|
||||
TEST(boost::long_long_type)
|
||||
TEST(boost::ulong_long_type)
|
||||
#endif
|
||||
|
||||
#if defined(BOOST_HAS_INT128)
|
||||
TEST(boost::int128_type)
|
||||
TEST(boost::uint128_type)
|
||||
#endif
|
||||
|
||||
TEST(float)
|
||||
TEST(double)
|
||||
TEST(long double)
|
||||
|
||||
TEST(std::size_t)
|
||||
TEST(std::ptrdiff_t)
|
||||
|
||||
return boost::report_errors();
|
||||
}
|
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 !defined(BOOST_NO_CXX17_HDR_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 !defined(BOOST_NO_CXX17_HDR_OPTIONAL)
|
||||
test_optional_int();
|
||||
test_optional_string();
|
||||
#else
|
||||
BOOST_LIGHTWEIGHT_TEST_OSTREAM << "<optional> not available." << std::endl;
|
||||
#endif
|
||||
return boost::report_errors();
|
||||
}
|
45
test/hash_pointer_test.cpp
Normal file
45
test/hash_pointer_test.cpp
Normal file
@ -0,0 +1,45 @@
|
||||
|
||||
// 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)
|
||||
|
||||
#include "./config.hpp"
|
||||
|
||||
#ifdef BOOST_HASH_TEST_STD_INCLUDES
|
||||
# include <functional>
|
||||
#else
|
||||
# include <boost/container_hash/hash.hpp>
|
||||
#endif
|
||||
|
||||
#include <boost/core/lightweight_test.hpp>
|
||||
#include <boost/limits.hpp>
|
||||
#include "./compile_time.hpp"
|
||||
|
||||
void pointer_tests()
|
||||
{
|
||||
compile_time_tests((int**) 0);
|
||||
compile_time_tests((void**) 0);
|
||||
|
||||
BOOST_HASH_TEST_NAMESPACE::hash<int*> x1;
|
||||
BOOST_HASH_TEST_NAMESPACE::hash<int*> x2;
|
||||
|
||||
int int1;
|
||||
int int2;
|
||||
|
||||
BOOST_TEST(x1(0) == x2(0));
|
||||
BOOST_TEST(x1(&int1) == x2(&int1));
|
||||
BOOST_TEST(x1(&int2) == x2(&int2));
|
||||
#if defined(BOOST_HASH_TEST_EXTENSIONS)
|
||||
BOOST_TEST(x1(&int1) == BOOST_HASH_TEST_NAMESPACE::hash_value(&int1));
|
||||
BOOST_TEST(x1(&int2) == BOOST_HASH_TEST_NAMESPACE::hash_value(&int2));
|
||||
|
||||
// This isn't specified in Peter's proposal:
|
||||
BOOST_TEST(x1(0) == 0);
|
||||
#endif
|
||||
}
|
||||
|
||||
int main()
|
||||
{
|
||||
pointer_tests();
|
||||
return boost::report_errors();
|
||||
}
|
85
test/hash_range_test.cpp
Normal file
85
test/hash_range_test.cpp
Normal file
@ -0,0 +1,85 @@
|
||||
|
||||
// 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)
|
||||
|
||||
#include "./config.hpp"
|
||||
|
||||
#if !defined(BOOST_HASH_TEST_EXTENSIONS)
|
||||
|
||||
int main() {}
|
||||
|
||||
#else
|
||||
|
||||
#ifdef BOOST_HASH_TEST_STD_INCLUDES
|
||||
# include <functional>
|
||||
#else
|
||||
# include <boost/container_hash/hash.hpp>
|
||||
#endif
|
||||
|
||||
#include <boost/core/lightweight_test.hpp>
|
||||
#include <boost/limits.hpp>
|
||||
#include <vector>
|
||||
|
||||
void hash_range_tests()
|
||||
{
|
||||
std::vector<int> empty, values1, values2, values3, values4, values5;
|
||||
values1.push_back(0);
|
||||
values2.push_back(10);
|
||||
values3.push_back(10);
|
||||
values3.push_back(20);
|
||||
values4.push_back(15);
|
||||
values4.push_back(75);
|
||||
values5.push_back(10);
|
||||
values5.push_back(20);
|
||||
values5.push_back(15);
|
||||
values5.push_back(75);
|
||||
values5.push_back(10);
|
||||
values5.push_back(20);
|
||||
|
||||
std::vector<int> x;
|
||||
|
||||
std::size_t x_seed = 0;
|
||||
BOOST_TEST(x_seed == BOOST_HASH_TEST_NAMESPACE::hash_range(x.begin(), x.end()));
|
||||
|
||||
BOOST_TEST(BOOST_HASH_TEST_NAMESPACE::hash_range(empty.begin(), empty.end())
|
||||
== BOOST_HASH_TEST_NAMESPACE::hash_range(x.begin(), x.end()));
|
||||
BOOST_TEST(BOOST_HASH_TEST_NAMESPACE::hash_range(empty.begin(), empty.end())
|
||||
!= BOOST_HASH_TEST_NAMESPACE::hash_range(values1.begin(), values1.end()));
|
||||
|
||||
x.push_back(10);
|
||||
BOOST_HASH_TEST_NAMESPACE::hash_combine(x_seed, 10);
|
||||
BOOST_TEST(x_seed == BOOST_HASH_TEST_NAMESPACE::hash_range(x.begin(), x.end()));
|
||||
|
||||
BOOST_TEST(BOOST_HASH_TEST_NAMESPACE::hash_range(empty.begin(), empty.end())
|
||||
!= BOOST_HASH_TEST_NAMESPACE::hash_range(x.begin(), x.end()));
|
||||
BOOST_TEST(BOOST_HASH_TEST_NAMESPACE::hash_range(values2.begin(), values2.end())
|
||||
== BOOST_HASH_TEST_NAMESPACE::hash_range(x.begin(), x.end()));
|
||||
|
||||
x.push_back(20);
|
||||
BOOST_HASH_TEST_NAMESPACE::hash_combine(x_seed, 20);
|
||||
BOOST_TEST(x_seed == BOOST_HASH_TEST_NAMESPACE::hash_range(x.begin(), x.end()));
|
||||
|
||||
BOOST_TEST(BOOST_HASH_TEST_NAMESPACE::hash_range(empty.begin(), empty.end())
|
||||
!= BOOST_HASH_TEST_NAMESPACE::hash_range(x.begin(), x.end()));
|
||||
BOOST_TEST(BOOST_HASH_TEST_NAMESPACE::hash_range(values2.begin(), values2.end())
|
||||
!= BOOST_HASH_TEST_NAMESPACE::hash_range(x.begin(), x.end()));
|
||||
BOOST_TEST(BOOST_HASH_TEST_NAMESPACE::hash_range(values3.begin(), values3.end())
|
||||
== BOOST_HASH_TEST_NAMESPACE::hash_range(x.begin(), x.end()));
|
||||
|
||||
std::size_t seed =
|
||||
BOOST_HASH_TEST_NAMESPACE::hash_range(values3.begin(), values3.end());
|
||||
BOOST_HASH_TEST_NAMESPACE::hash_range(seed, values4.begin(), values4.end());
|
||||
BOOST_HASH_TEST_NAMESPACE::hash_range(seed, x.begin(), x.end());
|
||||
BOOST_TEST(seed ==
|
||||
BOOST_HASH_TEST_NAMESPACE::hash_range(values5.begin(), values5.end()));
|
||||
}
|
||||
|
||||
int main()
|
||||
{
|
||||
hash_range_tests();
|
||||
|
||||
return boost::report_errors();
|
||||
}
|
||||
|
||||
#endif // TEST_EXTESNIONS
|
446
test/hash_reference_values.cpp
Normal file
446
test/hash_reference_values.cpp
Normal file
@ -0,0 +1,446 @@
|
||||
// Copyright 2021 Peter Dimov.
|
||||
// Distributed under the Boost Software License, Version 1.0.
|
||||
// https://www.boost.org/LICENSE_1_0.txt
|
||||
|
||||
#define _SILENCE_NONFLOATING_COMPLEX_DEPRECATION_WARNING
|
||||
|
||||
#include <boost/config/pragma_message.hpp>
|
||||
|
||||
#if defined(__GNUC__) && !defined(__clang__) && __cplusplus < 201100L
|
||||
|
||||
BOOST_PRAGMA_MESSAGE("Skipping test under GCC in C++98 mode")
|
||||
int main() {}
|
||||
|
||||
#else
|
||||
|
||||
#if defined(__clang__)
|
||||
# pragma clang diagnostic ignored "-Wlong-long"
|
||||
#endif
|
||||
|
||||
#if defined(__GNUC__)
|
||||
# pragma GCC diagnostic ignored "-Wsign-conversion"
|
||||
#endif
|
||||
|
||||
#include <boost/container_hash/hash.hpp>
|
||||
#include <boost/core/lightweight_test.hpp>
|
||||
#include <string>
|
||||
#include <vector>
|
||||
#include <list>
|
||||
#include <utility>
|
||||
#include <complex>
|
||||
#include <limits>
|
||||
#include <climits>
|
||||
#include <cfloat>
|
||||
#include <cstddef>
|
||||
|
||||
// This test checks whether hash values have changed
|
||||
|
||||
template<class T> std::size_t hv( T const& t )
|
||||
{
|
||||
return boost::hash<T>()( t );
|
||||
}
|
||||
|
||||
int main()
|
||||
{
|
||||
// char
|
||||
BOOST_TEST_EQ( hv('\x00'), 0 );
|
||||
BOOST_TEST_EQ( hv('A'), 'A' );
|
||||
BOOST_TEST_EQ( hv('\x7F'), 0x7F );
|
||||
|
||||
// signed char
|
||||
BOOST_TEST_EQ( hv((signed char)0), 0 );
|
||||
BOOST_TEST_EQ( hv((signed char)+1), +1 );
|
||||
BOOST_TEST_EQ( hv((signed char)-1), (std::size_t)-1 );
|
||||
BOOST_TEST_EQ( hv((signed char)+127), 127 );
|
||||
BOOST_TEST_EQ( hv((signed char)-128), (std::size_t)-128 );
|
||||
|
||||
// unsigned char
|
||||
BOOST_TEST_EQ( hv((unsigned char)0), 0 );
|
||||
BOOST_TEST_EQ( hv((unsigned char)1), 1 );
|
||||
BOOST_TEST_EQ( hv((unsigned char)255), 255 );
|
||||
|
||||
// short
|
||||
BOOST_TEST_EQ( hv((short)0), 0 );
|
||||
BOOST_TEST_EQ( hv((short)+1), 1 );
|
||||
BOOST_TEST_EQ( hv((short)-1), (std::size_t)-1 );
|
||||
BOOST_TEST_EQ( hv((short)+32767), 32767 );
|
||||
BOOST_TEST_EQ( hv((short)-32768), (std::size_t)-32768 );
|
||||
|
||||
// unsigned short
|
||||
BOOST_TEST_EQ( hv((unsigned short)0), 0 );
|
||||
BOOST_TEST_EQ( hv((unsigned short)1), 1 );
|
||||
BOOST_TEST_EQ( hv((unsigned short)65535), 65535 );
|
||||
|
||||
// int
|
||||
BOOST_TEST_EQ( hv(0), 0 );
|
||||
BOOST_TEST_EQ( hv(+1), 1 );
|
||||
BOOST_TEST_EQ( hv(-1), (std::size_t)-1 );
|
||||
BOOST_TEST_EQ( hv(+32767), 32767 );
|
||||
BOOST_TEST_EQ( hv(-32768), (std::size_t)-32768 );
|
||||
|
||||
// unsigned int
|
||||
BOOST_TEST_EQ( hv((unsigned)0), 0 );
|
||||
BOOST_TEST_EQ( hv((unsigned)1), 1 );
|
||||
BOOST_TEST_EQ( hv((unsigned)65535), 65535 );
|
||||
BOOST_TEST_EQ( hv((unsigned)-1), (std::size_t)(unsigned)-1 );
|
||||
|
||||
// long
|
||||
BOOST_TEST_EQ( hv(0L), 0 );
|
||||
BOOST_TEST_EQ( hv(+1L), 1 );
|
||||
BOOST_TEST_EQ( hv(-1L), (std::size_t)-1 );
|
||||
BOOST_TEST_EQ( hv(+32767L), 32767 );
|
||||
BOOST_TEST_EQ( hv(-32768L), (std::size_t)-32768 );
|
||||
|
||||
// unsigned long
|
||||
BOOST_TEST_EQ( hv(0UL), 0 );
|
||||
BOOST_TEST_EQ( hv(1UL), 1 );
|
||||
BOOST_TEST_EQ( hv(65535UL), 65535 );
|
||||
BOOST_TEST_EQ( hv((unsigned long)-1), (std::size_t)(unsigned long)-1 );
|
||||
|
||||
// long long
|
||||
BOOST_TEST_EQ( hv(0LL), 0 );
|
||||
BOOST_TEST_EQ( hv(+1LL), 1 );
|
||||
BOOST_TEST_EQ( hv(-1LL), (std::size_t)-1 );
|
||||
BOOST_TEST_EQ( hv(+32767LL), 32767 );
|
||||
BOOST_TEST_EQ( hv(-32768LL), (std::size_t)-32768 );
|
||||
|
||||
// unsigned long long
|
||||
BOOST_TEST_EQ( hv(0ULL), 0 );
|
||||
BOOST_TEST_EQ( hv(1ULL), 1 );
|
||||
BOOST_TEST_EQ( hv(65535ULL), 65535 );
|
||||
#if SIZE_MAX == 4294967295U
|
||||
BOOST_TEST_EQ( hv((unsigned long long)-1), 3221225537U );
|
||||
#else
|
||||
BOOST_TEST_EQ( hv((unsigned long long)-1), (std::size_t)-1 );
|
||||
#endif
|
||||
|
||||
#if defined(BOOST_HAS_INT128)
|
||||
|
||||
typedef boost::int128_type int128;
|
||||
|
||||
BOOST_TEST_EQ( hv((int128)0), 0 );
|
||||
BOOST_TEST_EQ( hv((int128)1), 1 );
|
||||
BOOST_TEST_EQ( hv((int128)-1), (std::size_t)-1 );
|
||||
BOOST_TEST_EQ( hv((int128)+32767), 32767 );
|
||||
BOOST_TEST_EQ( hv((int128)-32768), (std::size_t)-32768 );
|
||||
|
||||
typedef boost::uint128_type uint128;
|
||||
|
||||
BOOST_TEST_EQ( hv((uint128)0), 0 );
|
||||
BOOST_TEST_EQ( hv((uint128)1), 1 );
|
||||
BOOST_TEST_EQ( hv((uint128)65535), 65535 );
|
||||
|
||||
#if defined(BOOST_GCC) && BOOST_GCC < 100000
|
||||
|
||||
// This looks like some sort of miscompilation.
|
||||
// Under CI, both GHA and Appveyor GCCs produce this value.
|
||||
// But the exact same test on godbolt.org produces the correct
|
||||
// value, below.
|
||||
|
||||
// BOOST_TEST_EQ( hv((uint128)-1), 18446744073709551615ULL );
|
||||
|
||||
#else
|
||||
|
||||
BOOST_TEST_EQ( hv((uint128)-1), 13835058055282163777ULL );
|
||||
|
||||
#endif
|
||||
|
||||
#endif
|
||||
|
||||
// float
|
||||
BOOST_TEST_EQ( hv(0.0f), 0 );
|
||||
BOOST_TEST_EQ( hv(-0.0f), 0 );
|
||||
BOOST_TEST_EQ( hv(1.0f), 1065353216U );
|
||||
BOOST_TEST_EQ( hv(-1.0f), 3212836864U );
|
||||
BOOST_TEST_EQ( hv(3.14f), 1078523331U );
|
||||
BOOST_TEST_EQ( hv(-3.14f), 3226006979U );
|
||||
BOOST_TEST_EQ( hv(1e-38f), 7136238U );
|
||||
BOOST_TEST_EQ( hv(-1e-38f), 2154619886U );
|
||||
BOOST_TEST_EQ( hv(1e+38f), 2123789977U );
|
||||
BOOST_TEST_EQ( hv(-1e+38f), 4271273625U );
|
||||
BOOST_TEST_EQ( hv(std::numeric_limits<float>::infinity()), 2139095040U );
|
||||
BOOST_TEST_EQ( hv(-std::numeric_limits<float>::infinity()), 4286578688U );
|
||||
|
||||
// double
|
||||
BOOST_TEST_EQ( hv(0.0), 0 );
|
||||
BOOST_TEST_EQ( hv(-0.0), 0 );
|
||||
|
||||
#if SIZE_MAX == 4294967295U
|
||||
|
||||
BOOST_TEST_EQ( hv(1.0), 1072693248U );
|
||||
BOOST_TEST_EQ( hv(-1.0), 3220176896U );
|
||||
BOOST_TEST_EQ( hv(3.14), 2660156064U );
|
||||
BOOST_TEST_EQ( hv(-3.14), 512672416U );
|
||||
BOOST_TEST_EQ( hv(1e-308), 1553872728U );
|
||||
BOOST_TEST_EQ( hv(-1e-308), 3701356376U );
|
||||
BOOST_TEST_EQ( hv(1e+308), 2577739707U );
|
||||
BOOST_TEST_EQ( hv(-1e+308), 430256059U );
|
||||
BOOST_TEST_EQ( hv(std::numeric_limits<double>::infinity()), 2146435072U );
|
||||
BOOST_TEST_EQ( hv(-std::numeric_limits<double>::infinity()), 4293918720U );
|
||||
|
||||
#else
|
||||
|
||||
BOOST_TEST_EQ( hv(1.0), 4607182418800017408ULL );
|
||||
BOOST_TEST_EQ( hv(-1.0), 13830554455654793216ULL );
|
||||
BOOST_TEST_EQ( hv(3.14), 4614253070214989087ULL );
|
||||
BOOST_TEST_EQ( hv(-3.14), 13837625107069764895ULL );
|
||||
BOOST_TEST_EQ( hv(1e-308), 2024022533073106ULL );
|
||||
BOOST_TEST_EQ( hv(-1e-308), 9225396059387848914ULL );
|
||||
BOOST_TEST_EQ( hv(1e+308), 9214871658872686752ULL );
|
||||
BOOST_TEST_EQ( hv(-1e+308), 18438243695727462560ULL );
|
||||
BOOST_TEST_EQ( hv(std::numeric_limits<double>::infinity()), 9218868437227405312ULL );
|
||||
BOOST_TEST_EQ( hv(-std::numeric_limits<double>::infinity()), 18442240474082181120ULL );
|
||||
|
||||
#endif
|
||||
|
||||
// long double
|
||||
BOOST_TEST_EQ( hv(0.0L), 0 );
|
||||
BOOST_TEST_EQ( hv(-0.0L), 0 );
|
||||
|
||||
#if defined(_WIN32) && !defined(__GNUC__) // Under MS ABI, long double == double
|
||||
|
||||
#if SIZE_MAX == 4294967295U
|
||||
|
||||
BOOST_TEST_EQ( hv(1.0L), 1072693248U );
|
||||
BOOST_TEST_EQ( hv(-1.0L), 3220176896U );
|
||||
BOOST_TEST_EQ( hv(3.14L), 2660156064U );
|
||||
BOOST_TEST_EQ( hv(-3.14L), 512672416U );
|
||||
BOOST_TEST_EQ( hv(std::numeric_limits<long double>::infinity()), 2146435072U );
|
||||
BOOST_TEST_EQ( hv(-std::numeric_limits<long double>::infinity()), 4293918720U );
|
||||
|
||||
#else
|
||||
|
||||
BOOST_TEST_EQ( hv(1.0L), 4607182418800017408ULL );
|
||||
BOOST_TEST_EQ( hv(-1.0L), 13830554455654793216ULL );
|
||||
BOOST_TEST_EQ( hv(3.14L), 4614253070214989087ULL );
|
||||
BOOST_TEST_EQ( hv(-3.14L), 13837625107069764895ULL );
|
||||
BOOST_TEST_EQ( hv(std::numeric_limits<long double>::infinity()), 9218868437227405312ULL );
|
||||
BOOST_TEST_EQ( hv(-std::numeric_limits<long double>::infinity()), 18442240474082181120ULL );
|
||||
|
||||
#endif
|
||||
|
||||
#else
|
||||
|
||||
#if SIZE_MAX == 4294967295U
|
||||
|
||||
BOOST_TEST_EQ( hv(1.0L), 2684370943U );
|
||||
BOOST_TEST_EQ( hv(-1.0L), 2684403711U );
|
||||
BOOST_TEST_EQ( hv(3.14L), 83002659U );
|
||||
BOOST_TEST_EQ( hv(-3.14L), 82969891U );
|
||||
BOOST_TEST_EQ( hv(std::numeric_limits<long double>::infinity()), 0xA0007FFFu );
|
||||
BOOST_TEST_EQ( hv(-std::numeric_limits<long double>::infinity()), 0xA000FFFFu );
|
||||
|
||||
#else
|
||||
|
||||
BOOST_TEST_EQ( hv(1.0L), 11529215046068486143ULL );
|
||||
BOOST_TEST_EQ( hv(-1.0L), 11529215046068518911ULL );
|
||||
BOOST_TEST_EQ( hv(3.14L), 12059468778148142067ULL );
|
||||
BOOST_TEST_EQ( hv(-3.14L), 12059468778147191795ULL );
|
||||
BOOST_TEST_EQ( hv(std::numeric_limits<long double>::infinity()), 11529215046068502527ULL );
|
||||
BOOST_TEST_EQ( hv(-std::numeric_limits<long double>::infinity()), 11529215046068535295ULL );
|
||||
|
||||
#endif
|
||||
|
||||
#endif
|
||||
|
||||
// C array
|
||||
{
|
||||
int a1[] = { 0 };
|
||||
int a2[] = { 0, 0 };
|
||||
int a3[] = { 0, 0, 0 };
|
||||
|
||||
#if SIZE_MAX == 4294967295U
|
||||
|
||||
BOOST_TEST_EQ( hv(a1), 3864292196U );
|
||||
BOOST_TEST_EQ( hv(a2), 2842917718U );
|
||||
BOOST_TEST_EQ( hv(a3), 325752138U );
|
||||
|
||||
#else
|
||||
|
||||
BOOST_TEST_EQ( hv(a1), 3864292196ULL );
|
||||
BOOST_TEST_EQ( hv(a2), 14642545639667855512ULL );
|
||||
BOOST_TEST_EQ( hv(a3), 17867750819888810972ULL );
|
||||
|
||||
#endif
|
||||
}
|
||||
|
||||
// string
|
||||
#if SIZE_MAX == 4294967295U
|
||||
|
||||
BOOST_TEST_EQ( hv(std::string()), 0 );
|
||||
BOOST_TEST_EQ( hv(std::string("abc")), 1849538372U );
|
||||
BOOST_TEST_EQ( hv(std::string("\0", 1)), 3864292196U );
|
||||
BOOST_TEST_EQ( hv(std::string("\0\0", 2)), 2842917718U );
|
||||
BOOST_TEST_EQ( hv(std::string("\0\0\0", 3)), 325752138U );
|
||||
|
||||
#else
|
||||
|
||||
BOOST_TEST_EQ( hv(std::string()), 0 );
|
||||
BOOST_TEST_EQ( hv(std::string("abc")), 6420922261882292859ULL );
|
||||
BOOST_TEST_EQ( hv(std::string("\0", 1)), 3864292196ULL );
|
||||
BOOST_TEST_EQ( hv(std::string("\0\0", 2)), 14642545639667855512ULL );
|
||||
BOOST_TEST_EQ( hv(std::string("\0\0\0", 3)), 17867750819888810972ULL );
|
||||
|
||||
#endif
|
||||
|
||||
// pointer
|
||||
BOOST_TEST_EQ( hv((void*)0), 0 );
|
||||
BOOST_TEST_EQ( hv((void*)0x200014A0), 603985716U );
|
||||
|
||||
// complex<int>
|
||||
BOOST_TEST_EQ( hv(std::complex<int>(0, 0)), 0U );
|
||||
BOOST_TEST_EQ( hv(std::complex<int>(+1, 0)), 1U );
|
||||
BOOST_TEST_EQ( hv(std::complex<int>(0, +1)), 65U );
|
||||
|
||||
#if SIZE_MAX == 4294967295U
|
||||
|
||||
BOOST_TEST_EQ( hv(std::complex<int>(-1, 0)), 4294967295U );
|
||||
BOOST_TEST_EQ( hv(std::complex<int>(0, -1)), 3221225536U );
|
||||
|
||||
#else
|
||||
|
||||
BOOST_TEST_EQ( hv(std::complex<int>(-1, 0)), 18446744073709551615ULL );
|
||||
BOOST_TEST_EQ( hv(std::complex<int>(0, -1)), 13835058055282163776ULL );
|
||||
|
||||
#endif
|
||||
|
||||
// complex<float>
|
||||
BOOST_TEST_EQ( hv(std::complex<float>(0.0f, 0.0f)), 0U );
|
||||
BOOST_TEST_EQ( hv(std::complex<float>(+1.0f, 0.0f)), 1065353216U );
|
||||
BOOST_TEST_EQ( hv(std::complex<float>(-1.0f, 0.0f)), 3212836864U );
|
||||
|
||||
#if SIZE_MAX == 4294967295U
|
||||
|
||||
BOOST_TEST_EQ( hv(std::complex<float>(0.0f, +1.0f)), 3495952384U );
|
||||
BOOST_TEST_EQ( hv(std::complex<float>(0.0f, -1.0f)), 2959081472U );
|
||||
|
||||
#else
|
||||
|
||||
BOOST_TEST_EQ( hv(std::complex<float>(0.0f, +1.0f)), 67920461824ULL );
|
||||
BOOST_TEST_EQ( hv(std::complex<float>(0.0f, -1.0f)), 209117511680ULL );
|
||||
|
||||
#endif
|
||||
|
||||
// complex<double>
|
||||
BOOST_TEST_EQ( hv(std::complex<double>(0.0, 0.0)), 0U );
|
||||
|
||||
#if SIZE_MAX == 4294967295U
|
||||
|
||||
BOOST_TEST_EQ( hv(std::complex<double>(+1.0, 0.0)), 1072693248U );
|
||||
BOOST_TEST_EQ( hv(std::complex<double>(-1.0, 0.0)), 3220176896U );
|
||||
BOOST_TEST_EQ( hv(std::complex<double>(0.0, +1.0)), 873201664U );
|
||||
BOOST_TEST_EQ( hv(std::complex<double>(0.0, -1.0)), 2483814400U );
|
||||
|
||||
#else
|
||||
|
||||
BOOST_TEST_EQ( hv(std::complex<double>(+1.0, 0.0)), 4607182418800017408ULL );
|
||||
BOOST_TEST_EQ( hv(std::complex<double>(-1.0, 0.0)), 13830554455654793216ULL );
|
||||
BOOST_TEST_EQ( hv(std::complex<double>(0.0, +1.0)), 3750372589692780544ULL );
|
||||
BOOST_TEST_EQ( hv(std::complex<double>(0.0, -1.0)), 10667901617333862400ULL );
|
||||
|
||||
#endif
|
||||
|
||||
// pair
|
||||
#if SIZE_MAX == 4294967295U
|
||||
|
||||
BOOST_TEST_EQ( hv(std::make_pair(0, 0)), 2842917718U );
|
||||
BOOST_TEST_EQ( hv(std::make_pair(1, 2)), 2507434894U );
|
||||
BOOST_TEST_EQ( hv(std::make_pair(-1, -2)), 1874100199 );
|
||||
|
||||
#else
|
||||
|
||||
BOOST_TEST_EQ( hv(std::make_pair(0, 0)), 14642545639667855512ULL );
|
||||
BOOST_TEST_EQ( hv(std::make_pair(1, 2)), 3370697991563800380ULL );
|
||||
BOOST_TEST_EQ( hv(std::make_pair(-1, -2)), 4139767141999124554ULL );
|
||||
|
||||
#endif
|
||||
|
||||
// vector<char>
|
||||
#if SIZE_MAX == 4294967295U
|
||||
|
||||
BOOST_TEST_EQ( hv(std::vector<char>(0)), 0 );
|
||||
BOOST_TEST_EQ( hv(std::vector<char>(1)), 3864292196U );
|
||||
BOOST_TEST_EQ( hv(std::vector<char>(2)), 2842917718U );
|
||||
BOOST_TEST_EQ( hv(std::vector<char>(3)), 325752138U );
|
||||
|
||||
#else
|
||||
|
||||
BOOST_TEST_EQ( hv(std::vector<char>(0)), 0 );
|
||||
BOOST_TEST_EQ( hv(std::vector<char>(1)), 3864292196ULL );
|
||||
BOOST_TEST_EQ( hv(std::vector<char>(2)), 14642545639667855512ULL );
|
||||
BOOST_TEST_EQ( hv(std::vector<char>(3)), 17867750819888810972ULL );
|
||||
|
||||
#endif
|
||||
|
||||
// vector<int>
|
||||
#if SIZE_MAX == 4294967295U
|
||||
|
||||
BOOST_TEST_EQ( hv(std::vector<int>(0)), 0 );
|
||||
BOOST_TEST_EQ( hv(std::vector<int>(1)), 3864292196U );
|
||||
BOOST_TEST_EQ( hv(std::vector<int>(2)), 2842917718U );
|
||||
BOOST_TEST_EQ( hv(std::vector<int>(3)), 325752138U );
|
||||
|
||||
#else
|
||||
|
||||
BOOST_TEST_EQ( hv(std::vector<int>(0)), 0 );
|
||||
BOOST_TEST_EQ( hv(std::vector<int>(1)), 3864292196ULL );
|
||||
BOOST_TEST_EQ( hv(std::vector<int>(2)), 14642545639667855512ULL );
|
||||
BOOST_TEST_EQ( hv(std::vector<int>(3)), 17867750819888810972ULL );
|
||||
|
||||
#endif
|
||||
|
||||
// vector<vector<int>>
|
||||
#if SIZE_MAX == 4294967295U
|
||||
|
||||
BOOST_TEST_EQ( hv(std::vector<std::vector<int> >(0)), 0 );
|
||||
BOOST_TEST_EQ( hv(std::vector<std::vector<int> >(1)), 3864292196U );
|
||||
BOOST_TEST_EQ( hv(std::vector<std::vector<int> >(2)), 2842917718U );
|
||||
BOOST_TEST_EQ( hv(std::vector<std::vector<int> >(3)), 325752138U );
|
||||
|
||||
#else
|
||||
|
||||
BOOST_TEST_EQ( hv(std::vector<std::vector<int> >(0)), 0 );
|
||||
BOOST_TEST_EQ( hv(std::vector<std::vector<int> >(1)), 3864292196ULL );
|
||||
BOOST_TEST_EQ( hv(std::vector<std::vector<int> >(2)), 14642545639667855512ULL );
|
||||
BOOST_TEST_EQ( hv(std::vector<std::vector<int> >(3)), 17867750819888810972ULL );
|
||||
|
||||
#endif
|
||||
|
||||
// list<char>
|
||||
#if SIZE_MAX == 4294967295U
|
||||
|
||||
BOOST_TEST_EQ( hv(std::list<char>(0)), 0 );
|
||||
BOOST_TEST_EQ( hv(std::list<char>(1)), 3864292196U );
|
||||
BOOST_TEST_EQ( hv(std::list<char>(2)), 2842917718U );
|
||||
BOOST_TEST_EQ( hv(std::list<char>(3)), 325752138U );
|
||||
|
||||
#else
|
||||
|
||||
BOOST_TEST_EQ( hv(std::list<char>(0)), 0 );
|
||||
BOOST_TEST_EQ( hv(std::list<char>(1)), 3864292196ULL );
|
||||
BOOST_TEST_EQ( hv(std::list<char>(2)), 14642545639667855512ULL );
|
||||
BOOST_TEST_EQ( hv(std::list<char>(3)), 17867750819888810972ULL );
|
||||
|
||||
#endif
|
||||
|
||||
// list<int>
|
||||
#if SIZE_MAX == 4294967295U
|
||||
|
||||
BOOST_TEST_EQ( hv(std::list<int>(0)), 0 );
|
||||
BOOST_TEST_EQ( hv(std::list<int>(1)), 3864292196U );
|
||||
BOOST_TEST_EQ( hv(std::list<int>(2)), 2842917718U );
|
||||
BOOST_TEST_EQ( hv(std::list<int>(3)), 325752138U );
|
||||
|
||||
#else
|
||||
|
||||
BOOST_TEST_EQ( hv(std::list<int>(0)), 0 );
|
||||
BOOST_TEST_EQ( hv(std::list<int>(1)), 3864292196ULL );
|
||||
BOOST_TEST_EQ( hv(std::list<int>(2)), 14642545639667855512ULL );
|
||||
BOOST_TEST_EQ( hv(std::list<int>(3)), 17867750819888810972ULL );
|
||||
|
||||
#endif
|
||||
|
||||
return boost::report_errors();
|
||||
}
|
||||
|
||||
#endif
|
85
test/hash_sequence_test.hpp
Normal file
85
test/hash_sequence_test.hpp
Normal file
@ -0,0 +1,85 @@
|
||||
|
||||
// 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)
|
||||
|
||||
#if !defined(CONTAINER_TYPE)
|
||||
#error "CONTAINER_TYPE not defined"
|
||||
#else
|
||||
|
||||
#if defined(BOOST_MSVC)
|
||||
#pragma warning(push)
|
||||
#pragma warning(disable:4245) // signed/unsigned mismatch
|
||||
#endif
|
||||
|
||||
#if defined(__GNUC__) && __GNUC__ == 8
|
||||
# pragma GCC diagnostic push
|
||||
# pragma GCC diagnostic ignored "-Wsign-conversion"
|
||||
#endif
|
||||
|
||||
namespace HASH_TEST_CAT(CONTAINER_TYPE, _tests)
|
||||
{
|
||||
template <class T>
|
||||
void integer_tests(T* = 0)
|
||||
{
|
||||
typedef typename T::value_type value_type;
|
||||
|
||||
const int number_of_containers = 11;
|
||||
T containers[number_of_containers];
|
||||
|
||||
for(int i = 0; i < 5; ++i) {
|
||||
for(int j = 0; j < i; ++j)
|
||||
containers[i].push_back(0);
|
||||
}
|
||||
|
||||
containers[5].push_back(value_type(1));
|
||||
containers[6].push_back(value_type(1));
|
||||
containers[6].push_back(value_type(1));
|
||||
containers[7].push_back(value_type(-1));
|
||||
containers[8].push_back(value_type(-1));
|
||||
containers[8].push_back(value_type(-1));
|
||||
containers[9].push_back(value_type(1));
|
||||
containers[9].push_back(value_type(-1));
|
||||
containers[10].push_back(value_type(-1));
|
||||
containers[10].push_back(value_type(1));
|
||||
|
||||
BOOST_HASH_TEST_NAMESPACE::hash<T> hasher;
|
||||
|
||||
for(int i2 = 0; i2 < number_of_containers; ++i2) {
|
||||
BOOST_TEST(hasher(containers[i2]) == hasher(containers[i2]));
|
||||
|
||||
BOOST_TEST(hasher(containers[i2]) ==
|
||||
BOOST_HASH_TEST_NAMESPACE::hash_value(containers[i2]));
|
||||
|
||||
BOOST_TEST(hasher(containers[i2])
|
||||
== BOOST_HASH_TEST_NAMESPACE::hash_range(
|
||||
containers[i2].begin(), containers[i2].end()));
|
||||
|
||||
for(int j2 = i2 + 1; j2 < number_of_containers; ++j2) {
|
||||
BOOST_TEST(
|
||||
(containers[i2] == containers[j2]) ==
|
||||
(hasher(containers[i2]) == hasher(containers[j2]))
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void HASH_TEST_CAT(CONTAINER_TYPE, _hash_integer_tests())
|
||||
{
|
||||
integer_tests((CONTAINER_TYPE<char>*) 0);
|
||||
integer_tests((CONTAINER_TYPE<int>*) 0);
|
||||
integer_tests((CONTAINER_TYPE<unsigned long>*) 0);
|
||||
integer_tests((CONTAINER_TYPE<double>*) 0);
|
||||
}
|
||||
}
|
||||
|
||||
#if defined(__GNUC__) && __GNUC__ == 8
|
||||
# pragma GCC diagnostic pop
|
||||
#endif
|
||||
|
||||
#if defined(BOOST_MSVC)
|
||||
#pragma warning(pop)
|
||||
#endif
|
||||
|
||||
#undef CONTAINER_TYPE
|
||||
#endif
|
40
test/hash_set_test.cpp
Normal file
40
test/hash_set_test.cpp
Normal file
@ -0,0 +1,40 @@
|
||||
|
||||
// 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)
|
||||
|
||||
#include "./config.hpp"
|
||||
|
||||
#ifdef BOOST_HASH_TEST_EXTENSIONS
|
||||
# ifdef BOOST_HASH_TEST_STD_INCLUDES
|
||||
# include <functional>
|
||||
# else
|
||||
# include <boost/container_hash/hash.hpp>
|
||||
# endif
|
||||
#endif
|
||||
|
||||
#include <boost/core/lightweight_test.hpp>
|
||||
|
||||
#ifdef BOOST_HASH_TEST_EXTENSIONS
|
||||
|
||||
#include <set>
|
||||
|
||||
using std::set;
|
||||
#define CONTAINER_TYPE set
|
||||
#include "./hash_set_test.hpp"
|
||||
|
||||
using std::multiset;
|
||||
#define CONTAINER_TYPE multiset
|
||||
#include "./hash_set_test.hpp"
|
||||
|
||||
#endif
|
||||
|
||||
int main()
|
||||
{
|
||||
#ifdef BOOST_HASH_TEST_EXTENSIONS
|
||||
set_tests::set_hash_integer_tests();
|
||||
multiset_tests::multiset_hash_integer_tests();
|
||||
#endif
|
||||
|
||||
return boost::report_errors();
|
||||
}
|
88
test/hash_set_test.hpp
Normal file
88
test/hash_set_test.hpp
Normal file
@ -0,0 +1,88 @@
|
||||
|
||||
// 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)
|
||||
|
||||
#if !defined(CONTAINER_TYPE)
|
||||
#error "CONTAINER_TYPE not defined"
|
||||
#else
|
||||
|
||||
#if defined(BOOST_MSVC)
|
||||
#pragma warning(push)
|
||||
#pragma warning(disable:4245) // signed/unsigned mismatch
|
||||
#endif
|
||||
|
||||
#if defined(__GNUC__) && __GNUC__ == 8
|
||||
# pragma GCC diagnostic push
|
||||
# pragma GCC diagnostic ignored "-Wsign-conversion"
|
||||
#endif
|
||||
|
||||
namespace HASH_TEST_CAT(CONTAINER_TYPE, _tests)
|
||||
{
|
||||
template <class T>
|
||||
void integer_tests(T* = 0)
|
||||
{
|
||||
typedef typename T::value_type value_type;
|
||||
|
||||
const int number_of_containers = 12;
|
||||
T containers[number_of_containers];
|
||||
|
||||
for(int i = 0; i < 5; ++i) {
|
||||
for(int j = 0; j < i; ++j)
|
||||
containers[i].insert(0);
|
||||
}
|
||||
|
||||
containers[6].insert(value_type(1));
|
||||
containers[7].insert(value_type(1));
|
||||
containers[7].insert(value_type(1));
|
||||
containers[8].insert(value_type(-1));
|
||||
containers[9].insert(value_type(-1));
|
||||
containers[9].insert(value_type(-1));
|
||||
containers[10].insert(value_type(-1));
|
||||
containers[10].insert(value_type(1));
|
||||
containers[11].insert(value_type(1));
|
||||
containers[11].insert(value_type(2));
|
||||
containers[11].insert(value_type(3));
|
||||
containers[11].insert(value_type(4));
|
||||
containers[11].insert(value_type(5));
|
||||
|
||||
BOOST_HASH_TEST_NAMESPACE::hash<T> hasher;
|
||||
|
||||
for(int i2 = 0; i2 < number_of_containers; ++i2) {
|
||||
BOOST_TEST(hasher(containers[i2]) == hasher(containers[i2]));
|
||||
|
||||
BOOST_TEST(hasher(containers[i2]) ==
|
||||
BOOST_HASH_TEST_NAMESPACE::hash_value(containers[i2]));
|
||||
|
||||
BOOST_TEST(hasher(containers[i2])
|
||||
== BOOST_HASH_TEST_NAMESPACE::hash_range(
|
||||
containers[i2].begin(), containers[i2].end()));
|
||||
|
||||
for(int j2 = i2 + 1; j2 < number_of_containers; ++j2) {
|
||||
BOOST_TEST(
|
||||
(containers[i2] == containers[j2]) ==
|
||||
(hasher(containers[i2]) == hasher(containers[j2]))
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void HASH_TEST_CAT(CONTAINER_TYPE, _hash_integer_tests())
|
||||
{
|
||||
integer_tests((CONTAINER_TYPE<char>*) 0);
|
||||
integer_tests((CONTAINER_TYPE<int>*) 0);
|
||||
integer_tests((CONTAINER_TYPE<unsigned long>*) 0);
|
||||
integer_tests((CONTAINER_TYPE<double>*) 0);
|
||||
}
|
||||
}
|
||||
|
||||
#if defined(__GNUC__) && __GNUC__ == 8
|
||||
# pragma GCC diagnostic pop
|
||||
#endif
|
||||
|
||||
#if defined(BOOST_MSVC)
|
||||
#pragma warning(pop)
|
||||
#endif
|
||||
|
||||
#undef CONTAINER_TYPE
|
||||
#endif
|
103
test/hash_std_array_test.cpp
Normal file
103
test/hash_std_array_test.cpp
Normal file
@ -0,0 +1,103 @@
|
||||
|
||||
// Copyright 2012 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"
|
||||
|
||||
#ifdef BOOST_HASH_TEST_EXTENSIONS
|
||||
# ifdef BOOST_HASH_TEST_STD_INCLUDES
|
||||
# include <functional>
|
||||
# else
|
||||
# include <boost/container_hash/hash.hpp>
|
||||
# endif
|
||||
#endif
|
||||
|
||||
#include <boost/config.hpp>
|
||||
#include <boost/core/lightweight_test.hpp>
|
||||
|
||||
#if defined(BOOST_HASH_TEST_EXTENSIONS) && !defined(BOOST_NO_CXX11_HDR_ARRAY)
|
||||
#define TEST_ARRAY
|
||||
#include <array>
|
||||
#include <vector>
|
||||
#endif
|
||||
|
||||
#ifdef TEST_ARRAY
|
||||
|
||||
template <typename T>
|
||||
void array_tests(T const& v) {
|
||||
boost::hash<typename T::value_type> hf;
|
||||
for(typename T::const_iterator i = v.begin(); i != v.end(); ++i) {
|
||||
for(typename T::const_iterator j = v.begin(); j != v.end(); ++j) {
|
||||
if (i != j)
|
||||
BOOST_TEST(hf(*i) != hf(*j));
|
||||
else
|
||||
BOOST_TEST(hf(*i) == hf(*j));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void empty_array_test() {
|
||||
/*
|
||||
boost::hash<std::array<int, 0> > empty_array_hash;
|
||||
std::array<int, 0> empty_array;
|
||||
BOOST_TEST(empty_array_hash(empty_array) == boost::hash_value(empty_array));
|
||||
*/
|
||||
}
|
||||
|
||||
void int_1_array_test()
|
||||
{
|
||||
std::vector<std::array<int, 1> > arrays;
|
||||
std::array<int, 1> val;
|
||||
val[0] = 0;
|
||||
arrays.push_back(val);
|
||||
val[0] = 1;
|
||||
arrays.push_back(val);
|
||||
val[0] = 2;
|
||||
arrays.push_back(val);
|
||||
array_tests(arrays);
|
||||
}
|
||||
|
||||
void string_1_array_test()
|
||||
{
|
||||
std::vector<std::array<std::string, 1> > arrays;
|
||||
std::array<std::string, 1> val;
|
||||
arrays.push_back(val);
|
||||
val[0] = "one";
|
||||
arrays.push_back(val);
|
||||
val[0] = "two";
|
||||
arrays.push_back(val);
|
||||
array_tests(arrays);
|
||||
}
|
||||
|
||||
void string_3_array_test()
|
||||
{
|
||||
std::vector<std::array<std::string,3 > > arrays;
|
||||
std::array<std::string, 3> val;
|
||||
arrays.push_back(val);
|
||||
val[0] = "one";
|
||||
arrays.push_back(val);
|
||||
val[0] = ""; val[1] = "one"; val[2] = "";
|
||||
arrays.push_back(val);
|
||||
val[0] = ""; val[1] = ""; val[2] = "one";
|
||||
arrays.push_back(val);
|
||||
val[0] = "one"; val[1] = "one"; val[2] = "one";
|
||||
arrays.push_back(val);
|
||||
val[0] = "one"; val[1] = "two"; val[2] = "three";
|
||||
arrays.push_back(val);
|
||||
array_tests(arrays);
|
||||
}
|
||||
|
||||
#endif // TEST_ARRAY
|
||||
|
||||
int main()
|
||||
{
|
||||
#ifdef TEST_ARRAY
|
||||
empty_array_test();
|
||||
int_1_array_test();
|
||||
string_1_array_test();
|
||||
string_3_array_test();
|
||||
#endif
|
||||
|
||||
return boost::report_errors();
|
||||
}
|
80
test/hash_std_smart_ptr_test.cpp
Normal file
80
test/hash_std_smart_ptr_test.cpp
Normal file
@ -0,0 +1,80 @@
|
||||
|
||||
// Copyright 2012 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"
|
||||
|
||||
#ifdef BOOST_HASH_TEST_STD_INCLUDES
|
||||
# include <functional>
|
||||
#else
|
||||
# include <boost/container_hash/hash.hpp>
|
||||
#endif
|
||||
|
||||
#include <boost/core/lightweight_test.hpp>
|
||||
#include "./compile_time.hpp"
|
||||
|
||||
#if defined(BOOST_HASH_TEST_EXTENSIONS) && !defined(BOOST_NO_CXX11_SMART_PTR)
|
||||
#define TEST_SMART_PTRS
|
||||
#include <memory>
|
||||
#endif
|
||||
|
||||
#ifdef TEST_SMART_PTRS
|
||||
|
||||
void shared_ptr_tests()
|
||||
{
|
||||
std::shared_ptr<int> x;
|
||||
compile_time_tests(&x);
|
||||
|
||||
BOOST_HASH_TEST_NAMESPACE::hash<std::shared_ptr<int> > x1;
|
||||
BOOST_HASH_TEST_NAMESPACE::hash<std::shared_ptr<int> > x2;
|
||||
|
||||
std::shared_ptr<int> ptr1(new int(10));
|
||||
std::shared_ptr<int> ptr2;
|
||||
|
||||
BOOST_TEST(x1(x) == x2(ptr2));
|
||||
BOOST_TEST(x1(x) != x2(ptr1));
|
||||
ptr2.reset(new int(10));
|
||||
BOOST_TEST(x1(ptr1) == x2(ptr1));
|
||||
BOOST_TEST(x1(ptr1) != x2(ptr2));
|
||||
ptr2 = ptr1;
|
||||
BOOST_TEST(x1(ptr1) == x2(ptr2));
|
||||
#if defined(BOOST_HASH_TEST_EXTENSIONS)
|
||||
BOOST_TEST(x1(x) == BOOST_HASH_TEST_NAMESPACE::hash_value(x));
|
||||
BOOST_TEST(x1(ptr1) == BOOST_HASH_TEST_NAMESPACE::hash_value(ptr2));
|
||||
#endif
|
||||
}
|
||||
|
||||
void unique_ptr_tests()
|
||||
{
|
||||
std::unique_ptr<int> x;
|
||||
compile_time_tests(&x);
|
||||
|
||||
BOOST_HASH_TEST_NAMESPACE::hash<std::unique_ptr<int> > x1;
|
||||
BOOST_HASH_TEST_NAMESPACE::hash<std::unique_ptr<int> > x2;
|
||||
|
||||
std::unique_ptr<int> ptr1(new int(10));
|
||||
std::unique_ptr<int> ptr2;
|
||||
|
||||
BOOST_TEST(x1(x) == x2(ptr2));
|
||||
BOOST_TEST(x1(x) != x2(ptr1));
|
||||
ptr2.reset(new int(10));
|
||||
BOOST_TEST(x1(ptr1) == x2(ptr1));
|
||||
BOOST_TEST(x1(ptr1) != x2(ptr2));
|
||||
|
||||
#if defined(BOOST_HASH_TEST_EXTENSIONS)
|
||||
BOOST_TEST(x1(x) == BOOST_HASH_TEST_NAMESPACE::hash_value(x));
|
||||
#endif
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
int main()
|
||||
{
|
||||
#ifdef TEST_SMART_PTRS
|
||||
shared_ptr_tests();
|
||||
unique_ptr_tests();
|
||||
#endif
|
||||
|
||||
return boost::report_errors();
|
||||
}
|
77
test/hash_std_tuple_test.cpp
Normal file
77
test/hash_std_tuple_test.cpp
Normal file
@ -0,0 +1,77 @@
|
||||
|
||||
// Copyright 2012 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"
|
||||
|
||||
#ifdef BOOST_HASH_TEST_EXTENSIONS
|
||||
# ifdef BOOST_HASH_TEST_STD_INCLUDES
|
||||
# include <functional>
|
||||
# else
|
||||
# include <boost/container_hash/hash.hpp>
|
||||
# endif
|
||||
#endif
|
||||
|
||||
#include <boost/config.hpp>
|
||||
#include <boost/core/lightweight_test.hpp>
|
||||
|
||||
#if defined(BOOST_HASH_TEST_EXTENSIONS) && !defined(BOOST_NO_CXX11_HDR_TUPLE)
|
||||
#define TEST_TUPLE
|
||||
#include <tuple>
|
||||
#include <vector>
|
||||
#endif
|
||||
|
||||
#ifdef TEST_TUPLE
|
||||
|
||||
template <typename T>
|
||||
void tuple_tests(T const& v) {
|
||||
boost::hash<typename T::value_type> hf;
|
||||
for(typename T::const_iterator i = v.begin(); i != v.end(); ++i) {
|
||||
for(typename T::const_iterator j = v.begin(); j != v.end(); ++j) {
|
||||
if (i != j)
|
||||
BOOST_TEST(hf(*i) != hf(*j));
|
||||
else
|
||||
BOOST_TEST(hf(*i) == hf(*j));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void empty_tuple_test() {
|
||||
boost::hash<std::tuple<> > empty_tuple_hash;
|
||||
std::tuple<> empty_tuple;
|
||||
BOOST_TEST(empty_tuple_hash(empty_tuple) == boost::hash_value(empty_tuple));
|
||||
}
|
||||
|
||||
void int_tuple_test() {
|
||||
std::vector<std::tuple<int> > int_tuples;
|
||||
int_tuples.push_back(std::make_tuple(0));
|
||||
int_tuples.push_back(std::make_tuple(1));
|
||||
int_tuples.push_back(std::make_tuple(2));
|
||||
tuple_tests(int_tuples);
|
||||
}
|
||||
|
||||
void int_string_tuple_test() {
|
||||
std::vector<std::tuple<int, std::string> > int_string_tuples;
|
||||
int_string_tuples.push_back(std::make_tuple(0, std::string("zero")));
|
||||
int_string_tuples.push_back(std::make_tuple(1, std::string("one")));
|
||||
int_string_tuples.push_back(std::make_tuple(2, std::string("two")));
|
||||
int_string_tuples.push_back(std::make_tuple(0, std::string("one")));
|
||||
int_string_tuples.push_back(std::make_tuple(1, std::string("zero")));
|
||||
int_string_tuples.push_back(std::make_tuple(0, std::string("")));
|
||||
int_string_tuples.push_back(std::make_tuple(1, std::string("")));
|
||||
tuple_tests(int_string_tuples);
|
||||
}
|
||||
|
||||
#endif // TEST_TUPLE
|
||||
|
||||
int main()
|
||||
{
|
||||
#ifdef TEST_TUPLE
|
||||
empty_tuple_test();
|
||||
int_tuple_test();
|
||||
int_string_tuple_test();
|
||||
#endif
|
||||
|
||||
return boost::report_errors();
|
||||
}
|
184
test/hash_string_test.cpp
Normal file
184
test/hash_string_test.cpp
Normal file
@ -0,0 +1,184 @@
|
||||
|
||||
// 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)
|
||||
|
||||
#include "./config.hpp"
|
||||
|
||||
#ifdef BOOST_HASH_TEST_STD_INCLUDES
|
||||
# include <functional>
|
||||
#else
|
||||
# include <boost/container_hash/hash.hpp>
|
||||
#endif
|
||||
|
||||
#include <boost/core/lightweight_test.hpp>
|
||||
#include <string>
|
||||
#include "./compile_time.hpp"
|
||||
|
||||
void string_tests()
|
||||
{
|
||||
compile_time_tests((std::string*) 0);
|
||||
|
||||
BOOST_HASH_TEST_NAMESPACE::hash<std::string> x1;
|
||||
BOOST_HASH_TEST_NAMESPACE::hash<std::string> x2;
|
||||
|
||||
BOOST_TEST(x1("Hello") == x2(std::string("Hel") + "lo"));
|
||||
BOOST_TEST(x1("") == x2(std::string()));
|
||||
|
||||
#if defined(BOOST_HASH_TEST_EXTENSIONS)
|
||||
std::string value1;
|
||||
std::string value2("Hello");
|
||||
|
||||
BOOST_TEST(x1(value1) == BOOST_HASH_TEST_NAMESPACE::hash_value(value1));
|
||||
BOOST_TEST(x1(value2) == BOOST_HASH_TEST_NAMESPACE::hash_value(value2));
|
||||
BOOST_TEST(BOOST_HASH_TEST_NAMESPACE::hash_value(value1) ==
|
||||
BOOST_HASH_TEST_NAMESPACE::hash_range(value1.begin(), value1.end()));
|
||||
BOOST_TEST(BOOST_HASH_TEST_NAMESPACE::hash_value(value2) ==
|
||||
BOOST_HASH_TEST_NAMESPACE::hash_range(value2.begin(), value2.end()));
|
||||
#endif
|
||||
}
|
||||
|
||||
void string0_tests()
|
||||
{
|
||||
std::string x1(1, '\0');
|
||||
std::string x2(2, '\0');
|
||||
std::string x3(3, '\0');
|
||||
std::string x4(10, '\0');
|
||||
|
||||
BOOST_HASH_TEST_NAMESPACE::hash<std::string> hasher;
|
||||
|
||||
BOOST_TEST(hasher(x1) != hasher(x2));
|
||||
BOOST_TEST(hasher(x1) != hasher(x3));
|
||||
BOOST_TEST(hasher(x1) != hasher(x4));
|
||||
BOOST_TEST(hasher(x2) != hasher(x3));
|
||||
BOOST_TEST(hasher(x2) != hasher(x4));
|
||||
BOOST_TEST(hasher(x3) != hasher(x4));
|
||||
}
|
||||
|
||||
#if !defined(BOOST_NO_STD_WSTRING) && !defined(BOOST_NO_INTRINSIC_WCHAR_T)
|
||||
void wstring_tests()
|
||||
{
|
||||
compile_time_tests((std::wstring*) 0);
|
||||
|
||||
BOOST_HASH_TEST_NAMESPACE::hash<std::wstring> x1;
|
||||
BOOST_HASH_TEST_NAMESPACE::hash<std::wstring> x2;
|
||||
|
||||
BOOST_TEST(x1(L"Hello") == x2(std::wstring(L"Hel") + L"lo"));
|
||||
BOOST_TEST(x1(L"") == x2(std::wstring()));
|
||||
|
||||
#if defined(BOOST_HASH_TEST_EXTENSIONS)
|
||||
std::wstring value1;
|
||||
std::wstring value2(L"Hello");
|
||||
|
||||
BOOST_TEST(x1(value1) == BOOST_HASH_TEST_NAMESPACE::hash_value(value1));
|
||||
BOOST_TEST(x1(value2) == BOOST_HASH_TEST_NAMESPACE::hash_value(value2));
|
||||
BOOST_TEST(BOOST_HASH_TEST_NAMESPACE::hash_value(value1) ==
|
||||
BOOST_HASH_TEST_NAMESPACE::hash_range(value1.begin(), value1.end()));
|
||||
BOOST_TEST(BOOST_HASH_TEST_NAMESPACE::hash_value(value2) ==
|
||||
BOOST_HASH_TEST_NAMESPACE::hash_range(value2.begin(), value2.end()));
|
||||
#endif
|
||||
}
|
||||
#endif
|
||||
|
||||
#if !defined(BOOST_NO_CXX11_CHAR16_T)
|
||||
void u16string_tests()
|
||||
{
|
||||
compile_time_tests((std::u16string*) 0);
|
||||
|
||||
BOOST_HASH_TEST_NAMESPACE::hash<std::u16string> x1;
|
||||
BOOST_HASH_TEST_NAMESPACE::hash<std::u16string> x2;
|
||||
|
||||
BOOST_TEST(x1(u"Hello") == x2(std::u16string(u"Hel") + u"lo"));
|
||||
BOOST_TEST(x1(u"") == x2(std::u16string()));
|
||||
|
||||
#if defined(BOOST_HASH_TEST_EXTENSIONS)
|
||||
std::u16string value1;
|
||||
std::u16string value2(u"Hello");
|
||||
|
||||
BOOST_TEST(x1(value1) == BOOST_HASH_TEST_NAMESPACE::hash_value(value1));
|
||||
BOOST_TEST(x1(value2) == BOOST_HASH_TEST_NAMESPACE::hash_value(value2));
|
||||
BOOST_TEST(BOOST_HASH_TEST_NAMESPACE::hash_value(value1) ==
|
||||
BOOST_HASH_TEST_NAMESPACE::hash_range(value1.begin(), value1.end()));
|
||||
BOOST_TEST(BOOST_HASH_TEST_NAMESPACE::hash_value(value2) ==
|
||||
BOOST_HASH_TEST_NAMESPACE::hash_range(value2.begin(), value2.end()));
|
||||
#endif
|
||||
}
|
||||
#endif
|
||||
|
||||
#if !defined(BOOST_NO_CXX11_CHAR32_T)
|
||||
void u32string_tests()
|
||||
{
|
||||
compile_time_tests((std::u32string*) 0);
|
||||
|
||||
BOOST_HASH_TEST_NAMESPACE::hash<std::u32string> x1;
|
||||
BOOST_HASH_TEST_NAMESPACE::hash<std::u32string> x2;
|
||||
|
||||
BOOST_TEST(x1(U"Hello") == x2(std::u32string(U"Hel") + U"lo"));
|
||||
BOOST_TEST(x1(U"") == x2(std::u32string()));
|
||||
|
||||
#if defined(BOOST_HASH_TEST_EXTENSIONS)
|
||||
std::u32string value1;
|
||||
std::u32string value2(U"Hello");
|
||||
|
||||
BOOST_TEST(x1(value1) == BOOST_HASH_TEST_NAMESPACE::hash_value(value1));
|
||||
BOOST_TEST(x1(value2) == BOOST_HASH_TEST_NAMESPACE::hash_value(value2));
|
||||
BOOST_TEST(BOOST_HASH_TEST_NAMESPACE::hash_value(value1) ==
|
||||
BOOST_HASH_TEST_NAMESPACE::hash_range(value1.begin(), value1.end()));
|
||||
BOOST_TEST(BOOST_HASH_TEST_NAMESPACE::hash_value(value2) ==
|
||||
BOOST_HASH_TEST_NAMESPACE::hash_range(value2.begin(), value2.end()));
|
||||
#endif
|
||||
}
|
||||
#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();
|
||||
string0_tests();
|
||||
#if !defined(BOOST_NO_STD_WSTRING) && !defined(BOOST_NO_INTRINSIC_WCHAR_T)
|
||||
wstring_tests();
|
||||
#endif
|
||||
#if !defined(BOOST_NO_CXX11_CHAR16_T)
|
||||
u16string_tests();
|
||||
#endif
|
||||
#if !defined(BOOST_NO_CXX11_CHAR32_T)
|
||||
u32string_tests();
|
||||
#endif
|
||||
|
||||
generic_string_tests((std::string*) 0);
|
||||
#if !defined(BOOST_NO_CXX17_HDR_STRING_VIEW)
|
||||
generic_string_tests((std::string_view*) 0);
|
||||
#endif
|
||||
|
||||
return boost::report_errors();
|
||||
}
|
51
test/hash_string_test2.cpp
Normal file
51
test/hash_string_test2.cpp
Normal file
@ -0,0 +1,51 @@
|
||||
// Copyright 2022 Peter Dimov.
|
||||
// Distributed under the Boost Software License, Version 1.0.
|
||||
// https://www.boost.org/LICENSE_1_0.txt
|
||||
|
||||
#include <boost/utility/string_view.hpp>
|
||||
#include <boost/core/detail/string_view.hpp>
|
||||
#include <boost/container_hash/hash.hpp>
|
||||
#include <boost/core/lightweight_test.hpp>
|
||||
#include <boost/config.hpp>
|
||||
#include <string>
|
||||
#if !defined(BOOST_NO_CXX17_HDR_STRING_VIEW)
|
||||
#include <string_view>
|
||||
#endif
|
||||
#include <vector>
|
||||
#include <deque>
|
||||
#include <list>
|
||||
#if !defined(BOOST_NO_CXX11_HDR_FORWARD_LIST)
|
||||
# include <forward_list>
|
||||
#endif
|
||||
|
||||
// Test whether the hash values of a string and a
|
||||
// string_view that refers to it match. This is
|
||||
// important for unordered heterogeneous lookups.
|
||||
|
||||
template<class T> std::size_t hv( T const& t )
|
||||
{
|
||||
return boost::hash<T>()( t );
|
||||
}
|
||||
|
||||
int main()
|
||||
{
|
||||
std::string s( "Test." );
|
||||
std::size_t h0 = hv( s );
|
||||
|
||||
BOOST_TEST_EQ( h0, hv( boost::string_view( s ) ) );
|
||||
BOOST_TEST_EQ( h0, hv( boost::core::string_view( s ) ) );
|
||||
|
||||
#if !defined(BOOST_NO_CXX17_HDR_STRING_VIEW)
|
||||
BOOST_TEST_EQ( h0, hv( std::string_view( s ) ) );
|
||||
#endif
|
||||
|
||||
BOOST_TEST_EQ( h0, hv( std::vector<char>( s.begin(), s.end() ) ) );
|
||||
BOOST_TEST_EQ( h0, hv( std::deque<char>( s.begin(), s.end() ) ) );
|
||||
BOOST_TEST_EQ( h0, hv( std::list<char>( s.begin(), s.end() ) ) );
|
||||
|
||||
#if !defined(BOOST_NO_CXX11_HDR_FORWARD_LIST)
|
||||
BOOST_TEST_EQ( h0, hv( std::forward_list<char>( s.begin(), s.end() ) ) );
|
||||
#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();
|
||||
}
|
53
test/hash_type_index_test.cpp
Normal file
53
test/hash_type_index_test.cpp
Normal file
@ -0,0 +1,53 @@
|
||||
|
||||
// Copyright 2011 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"
|
||||
|
||||
#ifdef BOOST_HASH_TEST_STD_INCLUDES
|
||||
# include <functional>
|
||||
#else
|
||||
# include <boost/container_hash/hash.hpp>
|
||||
#endif
|
||||
#include <boost/config.hpp>
|
||||
#include <boost/core/lightweight_test.hpp>
|
||||
|
||||
#if !defined(BOOST_NO_CXX11_HDR_TYPEINDEX)
|
||||
|
||||
#include <typeindex>
|
||||
|
||||
void test_type_index() {
|
||||
BOOST_HASH_TEST_NAMESPACE::hash<std::type_index> hasher;
|
||||
|
||||
#if defined(BOOST_NO_TYPEID)
|
||||
std::cout<<"Unable to test std::type_index, as typeid isn't available"
|
||||
<<std::endl;
|
||||
#else
|
||||
std::type_index int_index = typeid(int);
|
||||
std::type_index int2_index = typeid(int);
|
||||
std::type_index char_index = typeid(char);
|
||||
|
||||
BOOST_TEST(hasher(int_index) == int_index.hash_code());
|
||||
BOOST_TEST(hasher(int_index) == int2_index.hash_code());
|
||||
BOOST_TEST(hasher(char_index) == char_index.hash_code());
|
||||
BOOST_TEST(BOOST_HASH_TEST_NAMESPACE::hash_value(int_index) == int_index.hash_code());
|
||||
BOOST_TEST(BOOST_HASH_TEST_NAMESPACE::hash_value(int_index) == int2_index.hash_code());
|
||||
BOOST_TEST(BOOST_HASH_TEST_NAMESPACE::hash_value(char_index) == char_index.hash_code());
|
||||
|
||||
BOOST_TEST(hasher(int_index) == hasher(int2_index));
|
||||
BOOST_TEST(hasher(int_index) != hasher(char_index));
|
||||
#endif
|
||||
}
|
||||
#endif
|
||||
|
||||
int main()
|
||||
{
|
||||
#if !defined(BOOST_NO_CXX11_HDR_TYPEINDEX)
|
||||
test_type_index();
|
||||
#else
|
||||
std::cout<<"<type_index> not available."<<std::endl;
|
||||
#endif
|
||||
|
||||
return boost::report_errors();
|
||||
}
|
64
test/hash_value_array_test.cpp
Normal file
64
test/hash_value_array_test.cpp
Normal file
@ -0,0 +1,64 @@
|
||||
|
||||
// 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)
|
||||
|
||||
// On some compilers hash_value isn't available for arrays, so I test it
|
||||
// separately from the main array tests.
|
||||
|
||||
#include "./config.hpp"
|
||||
|
||||
#ifdef BOOST_HASH_TEST_EXTENSIONS
|
||||
# ifdef BOOST_HASH_TEST_STD_INCLUDES
|
||||
# include <functional>
|
||||
# else
|
||||
# include <boost/container_hash/hash.hpp>
|
||||
# endif
|
||||
#endif
|
||||
|
||||
#include <boost/core/lightweight_test.hpp>
|
||||
|
||||
#ifdef BOOST_HASH_TEST_EXTENSIONS
|
||||
|
||||
void array_int_test()
|
||||
{
|
||||
const int array1[25] = {
|
||||
26, -43, 32, 65, 45,
|
||||
12, 67, 32, 12, 23,
|
||||
0, 0, 0, 0, 0,
|
||||
8, -12, 23, 65, 45,
|
||||
-1, 93, -54, 987, 3
|
||||
};
|
||||
BOOST_HASH_TEST_NAMESPACE::hash<int[25]> hasher1;
|
||||
|
||||
int array2[1] = {3};
|
||||
BOOST_HASH_TEST_NAMESPACE::hash<int[1]> hasher2;
|
||||
|
||||
int array3[2] = {2, 3};
|
||||
BOOST_HASH_TEST_NAMESPACE::hash<int[2]> hasher3;
|
||||
|
||||
BOOST_TEST(hasher1(array1) == BOOST_HASH_TEST_NAMESPACE::hash_value(array1));
|
||||
BOOST_TEST(hasher2(array2) == BOOST_HASH_TEST_NAMESPACE::hash_value(array2));
|
||||
BOOST_TEST(hasher3(array3) == BOOST_HASH_TEST_NAMESPACE::hash_value(array3));
|
||||
}
|
||||
|
||||
void two_dimensional_array_test()
|
||||
{
|
||||
int array[3][2] = {{-5, 6}, {7, -3}, {26, 1}};
|
||||
BOOST_HASH_TEST_NAMESPACE::hash<int[3][2]> hasher;
|
||||
|
||||
BOOST_TEST(hasher(array) == BOOST_HASH_TEST_NAMESPACE::hash_value(array));
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
int main()
|
||||
{
|
||||
#ifdef BOOST_HASH_TEST_EXTENSIONS
|
||||
array_int_test();
|
||||
two_dimensional_array_test();
|
||||
#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 !defined(BOOST_NO_CXX17_HDR_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 !defined(BOOST_NO_CXX17_HDR_VARIANT)
|
||||
test_variant_int();
|
||||
test_variant_unique_types();
|
||||
#else
|
||||
BOOST_LIGHTWEIGHT_TEST_OSTREAM << "<variant> not available." << std::endl;
|
||||
#endif
|
||||
return boost::report_errors();
|
||||
}
|
68
test/hash_vector_test.cpp
Normal file
68
test/hash_vector_test.cpp
Normal file
@ -0,0 +1,68 @@
|
||||
|
||||
// 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)
|
||||
|
||||
#include "./config.hpp"
|
||||
|
||||
#ifdef BOOST_HASH_TEST_EXTENSIONS
|
||||
# ifdef BOOST_HASH_TEST_STD_INCLUDES
|
||||
# include <functional>
|
||||
# else
|
||||
# include <boost/container_hash/hash.hpp>
|
||||
# endif
|
||||
#endif
|
||||
|
||||
#include <boost/core/lightweight_test.hpp>
|
||||
|
||||
#ifdef BOOST_HASH_TEST_EXTENSIONS
|
||||
|
||||
#include <vector>
|
||||
|
||||
using std::vector;
|
||||
#define CONTAINER_TYPE vector
|
||||
#include "./hash_sequence_test.hpp"
|
||||
|
||||
#endif // BOOST_HASH_TEST_EXTENSIONS
|
||||
|
||||
namespace vector_bool_tests
|
||||
{
|
||||
void vector_bool_test() {
|
||||
std::vector<bool> x_empty1,x_empty2,x1,x1a,x2,x3;
|
||||
|
||||
x1.push_back(0);
|
||||
x1a.push_back(0);
|
||||
x2.push_back(1);
|
||||
x3.push_back(0);
|
||||
x3.push_back(0);
|
||||
|
||||
BOOST_HASH_TEST_NAMESPACE::hash<std::vector<bool> > hasher;
|
||||
|
||||
BOOST_TEST_EQ(hasher(x_empty1), hasher(x_empty1));
|
||||
BOOST_TEST_EQ(hasher(x_empty1), hasher(x_empty2));
|
||||
BOOST_TEST_NE(hasher(x_empty1), hasher(x1));
|
||||
BOOST_TEST_NE(hasher(x_empty1), hasher(x2));
|
||||
BOOST_TEST_NE(hasher(x_empty1), hasher(x3));
|
||||
|
||||
BOOST_TEST_EQ(hasher(x1), hasher(x1));
|
||||
BOOST_TEST_EQ(hasher(x1), hasher(x1a));
|
||||
BOOST_TEST_NE(hasher(x1), hasher(x2));
|
||||
BOOST_TEST_NE(hasher(x1), hasher(x3));
|
||||
|
||||
BOOST_TEST_EQ(hasher(x2), hasher(x2));
|
||||
BOOST_TEST_NE(hasher(x2), hasher(x3));
|
||||
|
||||
BOOST_TEST_EQ(hasher(x3), hasher(x3));
|
||||
}
|
||||
}
|
||||
|
||||
int main()
|
||||
{
|
||||
#ifdef BOOST_HASH_TEST_EXTENSIONS
|
||||
vector_tests::vector_hash_integer_tests();
|
||||
#endif
|
||||
|
||||
vector_bool_tests::vector_bool_test();
|
||||
|
||||
return boost::report_errors();
|
||||
}
|
21
test/implicit_test.cpp
Normal file
21
test/implicit_test.cpp
Normal file
@ -0,0 +1,21 @@
|
||||
|
||||
// Copyright 2010 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.hpp>
|
||||
|
||||
namespace test
|
||||
{
|
||||
struct base {};
|
||||
std::size_t hash_value(base const&) { return 0; }
|
||||
|
||||
struct converts { operator base() const { return base(); } };
|
||||
}
|
||||
|
||||
int main() {
|
||||
boost::hash<test::converts> hash;
|
||||
test::converts x;
|
||||
|
||||
hash(x);
|
||||
}
|
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user