Skip to content

Commit 243ddda

Browse files
Added support for custom hash functions in unordered containers; #414
1 parent c36baf8 commit 243ddda

5 files changed

Lines changed: 117 additions & 67 deletions

File tree

include/rfl/parsing/Parser_map_like.hpp

Lines changed: 17 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -18,29 +18,30 @@ namespace rfl {
1818
namespace parsing {
1919

2020
template <class R, class W, class T, class ProcessorsType>
21-
requires AreReaderAndWriter<R, W, std::map<std::string, T>>
21+
requires AreReaderAndWriter<R, W, std::map<std::string, T>>
2222
struct Parser<R, W, std::map<std::string, T>, ProcessorsType>
23-
: public MapParser<R, W, std::map<std::string, T>, ProcessorsType> {
24-
};
23+
: public MapParser<R, W, std::map<std::string, T>, ProcessorsType> {};
24+
25+
template <class R, class W, class T, class Hash, class KeyEqual,
26+
class Allocator, class ProcessorsType>
27+
requires AreReaderAndWriter<
28+
R, W, std::unordered_map<std::string, T, Hash, KeyEqual, Allocator>>
29+
struct Parser<R, W,
30+
std::unordered_map<std::string, T, Hash, KeyEqual, Allocator>,
31+
ProcessorsType>
32+
: public MapParser<
33+
R, W, std::unordered_map<std::string, T, Hash, KeyEqual, Allocator>,
34+
ProcessorsType> {};
2535

2636
template <class R, class W, class T, class ProcessorsType>
27-
requires AreReaderAndWriter<R, W, std::unordered_map<std::string, T>>
28-
struct Parser<R, W, std::unordered_map<std::string, T>, ProcessorsType>
29-
: public MapParser<R, W, std::unordered_map<std::string, T>,
30-
ProcessorsType> {
31-
};
32-
33-
template <class R, class W, class T, class ProcessorsType>
34-
requires AreReaderAndWriter<R, W, Object<T>>
37+
requires AreReaderAndWriter<R, W, Object<T>>
3538
struct Parser<R, W, Object<T>, ProcessorsType>
36-
: public MapParser<R, W, Object<T>, ProcessorsType> {
37-
};
39+
: public MapParser<R, W, Object<T>, ProcessorsType> {};
3840

3941
template <class R, class W, class T, class ProcessorsType>
40-
requires AreReaderAndWriter<R, W, ExtraFields<T>>
42+
requires AreReaderAndWriter<R, W, ExtraFields<T>>
4143
struct Parser<R, W, ExtraFields<T>, ProcessorsType>
42-
: public MapParser<R, W, ExtraFields<T>, ProcessorsType> {
43-
};
44+
: public MapParser<R, W, ExtraFields<T>, ProcessorsType> {};
4445

4546
} // namespace parsing
4647
} // namespace rfl

include/rfl/parsing/Parser_vector_like.hpp

Lines changed: 52 additions & 45 deletions
Original file line numberDiff line numberDiff line change
@@ -22,76 +22,83 @@ namespace rfl {
2222
namespace parsing {
2323

2424
template <class R, class W, class T, class ProcessorsType>
25-
requires AreReaderAndWriter<R, W, std::deque<T>>
25+
requires AreReaderAndWriter<R, W, std::deque<T>>
2626
struct Parser<R, W, std::deque<T>, ProcessorsType>
27-
: public VectorParser<R, W, std::deque<T>, ProcessorsType> {
28-
};
27+
: public VectorParser<R, W, std::deque<T>, ProcessorsType> {};
2928

3029
template <class R, class W, class T, class ProcessorsType>
31-
requires AreReaderAndWriter<R, W, std::forward_list<T>>
30+
requires AreReaderAndWriter<R, W, std::forward_list<T>>
3231
struct Parser<R, W, std::forward_list<T>, ProcessorsType>
33-
: public VectorParser<R, W, std::forward_list<T>, ProcessorsType> {
34-
};
32+
: public VectorParser<R, W, std::forward_list<T>, ProcessorsType> {};
3533

3634
template <class R, class W, class T, class ProcessorsType>
37-
requires AreReaderAndWriter<R, W, std::list<T>>
35+
requires AreReaderAndWriter<R, W, std::list<T>>
3836
struct Parser<R, W, std::list<T>, ProcessorsType>
39-
: public VectorParser<R, W, std::list<T>, ProcessorsType> {
40-
};
37+
: public VectorParser<R, W, std::list<T>, ProcessorsType> {};
4138

4239
template <class R, class W, class K, class V, class ProcessorsType>
43-
requires AreReaderAndWriter<R, W, std::map<K, V>>
40+
requires AreReaderAndWriter<R, W, std::map<K, V>>
4441
struct Parser<R, W, std::map<K, V>, ProcessorsType>
45-
: public VectorParser<R, W, std::map<K, V>, ProcessorsType> {
46-
};
42+
: public VectorParser<R, W, std::map<K, V>, ProcessorsType> {};
4743

4844
template <class R, class W, class K, class V, class ProcessorsType>
49-
requires AreReaderAndWriter<R, W, std::multimap<K, V>>
45+
requires AreReaderAndWriter<R, W, std::multimap<K, V>>
5046
struct Parser<R, W, std::multimap<K, V>, ProcessorsType>
51-
: public VectorParser<R, W, std::multimap<K, V>, ProcessorsType> {
52-
};
47+
: public VectorParser<R, W, std::multimap<K, V>, ProcessorsType> {};
5348

5449
template <class R, class W, class T, class ProcessorsType>
55-
requires AreReaderAndWriter<R, W, std::multiset<T>>
50+
requires AreReaderAndWriter<R, W, std::multiset<T>>
5651
struct Parser<R, W, std::multiset<T>, ProcessorsType>
57-
: public VectorParser<R, W, std::multiset<T>, ProcessorsType> {
58-
};
52+
: public VectorParser<R, W, std::multiset<T>, ProcessorsType> {};
5953

6054
template <class R, class W, class T, class ProcessorsType>
61-
requires AreReaderAndWriter<R, W, std::set<T>>
55+
requires AreReaderAndWriter<R, W, std::set<T>>
6256
struct Parser<R, W, std::set<T>, ProcessorsType>
63-
: public VectorParser<R, W, std::set<T>, ProcessorsType> {
64-
};
65-
66-
template <class R, class W, class K, class V, class ProcessorsType>
67-
requires AreReaderAndWriter<R, W, std::unordered_map<K, V>>
68-
struct Parser<R, W, std::unordered_map<K, V>, ProcessorsType>
69-
: public VectorParser<R, W, std::unordered_map<K, V>, ProcessorsType> {
70-
};
71-
72-
template <class R, class W, class T, class ProcessorsType>
73-
requires AreReaderAndWriter<R, W, std::unordered_multiset<T>>
74-
struct Parser<R, W, std::unordered_multiset<T>, ProcessorsType>
75-
: public VectorParser<R, W, std::unordered_multiset<T>, ProcessorsType> {
76-
};
77-
78-
template <class R, class W, class K, class V, class ProcessorsType>
79-
requires AreReaderAndWriter<R, W, std::unordered_multimap<K, V>>
80-
struct Parser<R, W, std::unordered_multimap<K, V>, ProcessorsType>
57+
: public VectorParser<R, W, std::set<T>, ProcessorsType> {};
58+
59+
template <class R, class W, class K, class V, class Hash, class KeyEqual,
60+
class Allocator, class ProcessorsType>
61+
requires AreReaderAndWriter<
62+
R, W, std::unordered_map<K, V, Hash, KeyEqual, Allocator>>
63+
struct Parser<R, W, std::unordered_map<K, V, Hash, KeyEqual, Allocator>,
64+
ProcessorsType>
65+
: public VectorParser<R, W,
66+
std::unordered_map<K, V, Hash, KeyEqual, Allocator>,
67+
ProcessorsType> {};
68+
69+
template <class R, class W, class T, class Hash, class KeyEqual,
70+
class Allocator, class ProcessorsType>
71+
requires AreReaderAndWriter<
72+
R, W, std::unordered_multiset<T, Hash, KeyEqual, Allocator>>
73+
struct Parser<R, W, std::unordered_multiset<T, Hash, KeyEqual, Allocator>,
74+
ProcessorsType>
75+
: public VectorParser<R, W,
76+
std::unordered_multiset<T, Hash, KeyEqual, Allocator>,
77+
ProcessorsType> {};
78+
79+
template <class R, class W, class K, class V, class Hash, class KeyEqual,
80+
class Allocator, class ProcessorsType>
81+
requires AreReaderAndWriter<
82+
R, W, std::unordered_multimap<K, V, Hash, KeyEqual, Allocator>>
83+
struct Parser<R, W, std::unordered_multimap<K, V, Hash, KeyEqual, Allocator>,
84+
ProcessorsType>
8185
: public VectorParser<R, W, std::unordered_multimap<K, V>, ProcessorsType> {
8286
};
8387

84-
template <class R, class W, class T, class ProcessorsType>
85-
requires AreReaderAndWriter<R, W, std::unordered_set<T>>
86-
struct Parser<R, W, std::unordered_set<T>, ProcessorsType>
87-
: public VectorParser<R, W, std::unordered_set<T>, ProcessorsType> {
88-
};
88+
template <class R, class W, class T, class Hash, class KeyEqual,
89+
class Allocator, class ProcessorsType>
90+
requires AreReaderAndWriter<R, W,
91+
std::unordered_set<T, Hash, KeyEqual, Allocator>>
92+
struct Parser<R, W, std::unordered_set<T, Hash, KeyEqual, Allocator>,
93+
ProcessorsType>
94+
: public VectorParser<R, W,
95+
std::unordered_set<T, Hash, KeyEqual, Allocator>,
96+
ProcessorsType> {};
8997

9098
template <class R, class W, class T, class ProcessorsType>
91-
requires AreReaderAndWriter<R, W, std::vector<T>>
99+
requires AreReaderAndWriter<R, W, std::vector<T>>
92100
struct Parser<R, W, std::vector<T>, ProcessorsType>
93-
: public VectorParser<R, W, std::vector<T>, ProcessorsType> {
94-
};
101+
: public VectorParser<R, W, std::vector<T>, ProcessorsType> {};
95102

96103
} // namespace parsing
97104
} // namespace rfl

include/rfl/parsing/is_map_like.hpp

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -20,11 +20,13 @@ class is_map_like<std::map<K, V>> : public std::true_type {};
2020
template <class K, class V>
2121
class is_map_like<std::multimap<K, V>> : public std::true_type {};
2222

23-
template <class K, class V>
24-
class is_map_like<std::unordered_map<K, V>> : public std::true_type {};
23+
template <class K, class V, class Hash, class KeyEqual, class Allocator>
24+
class is_map_like<std::unordered_map<K, V, Hash, KeyEqual, Allocator>>
25+
: public std::true_type {};
2526

26-
template <class K, class V>
27-
class is_map_like<std::unordered_multimap<K, V>> : public std::true_type {};
27+
template <class K, class V, class Hash, class KeyEqual, class Allocator>
28+
class is_map_like<std::unordered_multimap<K, V, Hash, KeyEqual, Allocator>>
29+
: public std::true_type {};
2830

2931
template <class T>
3032
constexpr bool is_map_like_v =

include/rfl/parsing/is_map_like_not_multimap.hpp

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -17,8 +17,9 @@ class is_map_like_not_multimap : public std::false_type {};
1717
template <class K, class V>
1818
class is_map_like_not_multimap<std::map<K, V>> : public std::true_type {};
1919

20-
template <class K, class V>
21-
class is_map_like_not_multimap<std::unordered_map<K, V>>
20+
template <class K, class V, class Hash, class KeyEqual, class Allocator>
21+
class is_map_like_not_multimap<
22+
std::unordered_map<K, V, Hash, KeyEqual, Allocator>>
2223
: public std::true_type {};
2324

2425
} // namespace parsing
Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,39 @@
1+
#include <iostream>
2+
#include <rfl.hpp>
3+
#include <rfl/json.hpp>
4+
#include <string>
5+
#include <unordered_map>
6+
7+
#include "write_and_read.hpp"
8+
9+
namespace test_unordered_map_with_custom_hash {
10+
11+
template <typename T>
12+
struct DummyHash {
13+
std::size_t operator()(const T& v) const { return std::hash<T>()(v); }
14+
};
15+
16+
struct Person {
17+
rfl::Rename<"firstName", std::string> first_name;
18+
rfl::Rename<"lastName", std::string> last_name = "Simpson";
19+
std::unique_ptr<std::unordered_map<int, Person, DummyHash<int>>> children;
20+
};
21+
22+
TEST(json, test_unordered_map_with_custom_hash) {
23+
auto children =
24+
std::make_unique<std::unordered_map<int, Person, DummyHash<int>>>();
25+
children->insert(std::make_pair(1, Person{.first_name = "Bart"}));
26+
children->insert(std::make_pair(2, Person{.first_name = "Lisa"}));
27+
children->insert(std::make_pair(3, Person{.first_name = "Maggie"}));
28+
29+
const auto homer =
30+
Person{.first_name = "Homer", .children = std::move(children)};
31+
32+
// Unordered maps are unpredictable. We therefore only make sure that this
33+
// compiles.
34+
const auto json_string = rfl::json::write(homer);
35+
const auto homer2 = rfl::json::read<Person>(json_string);
36+
37+
EXPECT_TRUE(true);
38+
}
39+
} // namespace test_unordered_map_with_custom_hash

0 commit comments

Comments
 (0)