Skip to content

Commit 98f3ac8

Browse files
committed
Enable lookup in constexpr std::array<std::pair<K, V>>
1 parent 1fa48ed commit 98f3ac8

File tree

14 files changed

+215
-175
lines changed

14 files changed

+215
-175
lines changed

include/graphqlservice/internal/SortedMap.h

Lines changed: 37 additions & 48 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,37 @@
1414

1515
namespace graphql::internal {
1616

17+
template <class K, class V>
18+
struct sorted_map_key
19+
{
20+
constexpr sorted_map_key(const std::pair<K, V>& entry) noexcept
21+
: key { entry.first }
22+
{
23+
}
24+
25+
constexpr sorted_map_key(const K& key) noexcept
26+
: key { key }
27+
{
28+
}
29+
30+
constexpr ~sorted_map_key() noexcept = default;
31+
32+
const K& key;
33+
};
34+
35+
template <class Compare, class Iterator, class K = decltype(std::declval<Iterator>()->first),
36+
class V = decltype(std::declval<Iterator>()->second)>
37+
constexpr std::pair<Iterator, Iterator> find_sorted_map_key(
38+
Iterator itrBegin, Iterator itrEnd, const K& key) noexcept
39+
{
40+
return std::equal_range(itrBegin,
41+
itrEnd,
42+
key,
43+
[](sorted_map_key<K, V> lhs, sorted_map_key<K, V> rhs) noexcept {
44+
return Compare {}(lhs.key, rhs.key);
45+
});
46+
};
47+
1748
template <class K, class V, class Compare = std::less<K>>
1849
class sorted_map
1950
{
@@ -93,14 +124,9 @@ class sorted_map
93124

94125
constexpr const_iterator find(const K& key) const noexcept
95126
{
96-
const auto [itr, itrEnd] = std::equal_range(begin(),
97-
end(),
98-
key,
99-
[](sorted_map_key lhs, sorted_map_key rhs) noexcept {
100-
return Compare {}(lhs.key, rhs.key);
101-
});
127+
const auto [itr, itrEnd] = find_sorted_map_key<Compare>(_data.begin(), _data.end(), key);
102128

103-
return itr == itrEnd ? _data.end() : itr;
129+
return itr == itrEnd ? _data.cend() : itr;
104130
}
105131

106132
template <typename KeyArg>
@@ -115,12 +141,7 @@ class sorted_map
115141
std::pair<const_iterator, bool> emplace(KeyArg&& keyArg, ValueArgs&&... args) noexcept
116142
{
117143
K key { std::forward<KeyArg>(keyArg) };
118-
const auto [itr, itrEnd] = std::equal_range(_data.begin(),
119-
_data.end(),
120-
key,
121-
[](sorted_map_key lhs, sorted_map_key rhs) noexcept {
122-
return Compare {}(lhs.key, rhs.key);
123-
});
144+
const auto [itr, itrEnd] = find_sorted_map_key<Compare>(_data.begin(), _data.end(), key);
124145

125146
if (itr != itrEnd)
126147
{
@@ -133,12 +154,7 @@ class sorted_map
133154

134155
const_iterator erase(const K& key) noexcept
135156
{
136-
const auto [itr, itrEnd] = std::equal_range(_data.begin(),
137-
_data.end(),
138-
key,
139-
[](sorted_map_key lhs, sorted_map_key rhs) noexcept {
140-
return Compare {}(lhs.key, rhs.key);
141-
});
157+
const auto [itr, itrEnd] = find_sorted_map_key<Compare>(_data.begin(), _data.end(), key);
142158

143159
if (itr == itrEnd)
144160
{
@@ -165,12 +181,7 @@ class sorted_map
165181
V& operator[](KeyArg&& keyArg) noexcept
166182
{
167183
K key { std::forward<KeyArg>(keyArg) };
168-
const auto [itr, itrEnd] = std::equal_range(_data.begin(),
169-
_data.end(),
170-
key,
171-
[](sorted_map_key lhs, sorted_map_key rhs) noexcept {
172-
return Compare {}(lhs.key, rhs.key);
173-
});
184+
const auto [itr, itrEnd] = find_sorted_map_key<Compare>(_data.begin(), _data.end(), key);
174185

175186
if (itr != itrEnd)
176187
{
@@ -184,12 +195,7 @@ class sorted_map
184195
V& at(KeyArg&& keyArg)
185196
{
186197
const K key { std::forward<KeyArg>(keyArg) };
187-
const auto [itr, itrEnd] = std::equal_range(_data.begin(),
188-
_data.end(),
189-
key,
190-
[](sorted_map_key lhs, sorted_map_key rhs) noexcept {
191-
return Compare {}(lhs.key, rhs.key);
192-
});
198+
const auto [itr, itrEnd] = find_sorted_map_key<Compare>(_data.begin(), _data.end(), key);
193199

194200
if (itr == itrEnd)
195201
{
@@ -200,23 +206,6 @@ class sorted_map
200206
}
201207

202208
private:
203-
struct sorted_map_key
204-
{
205-
constexpr sorted_map_key(const std::pair<K, V>& entry) noexcept
206-
: key { entry.first }
207-
{
208-
}
209-
210-
constexpr sorted_map_key(const K& key) noexcept
211-
: key { key }
212-
{
213-
}
214-
215-
constexpr ~sorted_map_key() noexcept = default;
216-
217-
const K& key;
218-
};
219-
220209
vector_type _data;
221210
};
222211

include/graphqlservice/introspection/IntrospectionSchema.h

Lines changed: 29 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -54,15 +54,15 @@ constexpr auto getTypeKindValues() noexcept
5454
{
5555
using namespace std::literals;
5656

57-
return internal::string_view_map<TypeKind> {
58-
{ R"gql(ENUM)gql"sv, TypeKind::ENUM },
59-
{ R"gql(LIST)gql"sv, TypeKind::LIST },
60-
{ R"gql(UNION)gql"sv, TypeKind::UNION },
61-
{ R"gql(OBJECT)gql"sv, TypeKind::OBJECT },
62-
{ R"gql(SCALAR)gql"sv, TypeKind::SCALAR },
63-
{ R"gql(NON_NULL)gql"sv, TypeKind::NON_NULL },
64-
{ R"gql(INTERFACE)gql"sv, TypeKind::INTERFACE },
65-
{ R"gql(INPUT_OBJECT)gql"sv, TypeKind::INPUT_OBJECT }
57+
return std::array<std::pair<std::string_view, TypeKind>, 8> {
58+
std::make_pair(R"gql(ENUM)gql"sv, TypeKind::ENUM),
59+
std::make_pair(R"gql(LIST)gql"sv, TypeKind::LIST),
60+
std::make_pair(R"gql(UNION)gql"sv, TypeKind::UNION),
61+
std::make_pair(R"gql(OBJECT)gql"sv, TypeKind::OBJECT),
62+
std::make_pair(R"gql(SCALAR)gql"sv, TypeKind::SCALAR),
63+
std::make_pair(R"gql(NON_NULL)gql"sv, TypeKind::NON_NULL),
64+
std::make_pair(R"gql(INTERFACE)gql"sv, TypeKind::INTERFACE),
65+
std::make_pair(R"gql(INPUT_OBJECT)gql"sv, TypeKind::INPUT_OBJECT)
6666
};
6767
}
6868

@@ -120,26 +120,26 @@ constexpr auto getDirectiveLocationValues() noexcept
120120
{
121121
using namespace std::literals;
122122

123-
return internal::string_view_map<DirectiveLocation> {
124-
{ R"gql(ENUM)gql"sv, DirectiveLocation::ENUM },
125-
{ R"gql(FIELD)gql"sv, DirectiveLocation::FIELD },
126-
{ R"gql(QUERY)gql"sv, DirectiveLocation::QUERY },
127-
{ R"gql(UNION)gql"sv, DirectiveLocation::UNION },
128-
{ R"gql(OBJECT)gql"sv, DirectiveLocation::OBJECT },
129-
{ R"gql(SCALAR)gql"sv, DirectiveLocation::SCALAR },
130-
{ R"gql(SCHEMA)gql"sv, DirectiveLocation::SCHEMA },
131-
{ R"gql(MUTATION)gql"sv, DirectiveLocation::MUTATION },
132-
{ R"gql(INTERFACE)gql"sv, DirectiveLocation::INTERFACE },
133-
{ R"gql(ENUM_VALUE)gql"sv, DirectiveLocation::ENUM_VALUE },
134-
{ R"gql(INPUT_OBJECT)gql"sv, DirectiveLocation::INPUT_OBJECT },
135-
{ R"gql(SUBSCRIPTION)gql"sv, DirectiveLocation::SUBSCRIPTION },
136-
{ R"gql(FRAGMENT_SPREAD)gql"sv, DirectiveLocation::FRAGMENT_SPREAD },
137-
{ R"gql(INLINE_FRAGMENT)gql"sv, DirectiveLocation::INLINE_FRAGMENT },
138-
{ R"gql(FIELD_DEFINITION)gql"sv, DirectiveLocation::FIELD_DEFINITION },
139-
{ R"gql(ARGUMENT_DEFINITION)gql"sv, DirectiveLocation::ARGUMENT_DEFINITION },
140-
{ R"gql(FRAGMENT_DEFINITION)gql"sv, DirectiveLocation::FRAGMENT_DEFINITION },
141-
{ R"gql(VARIABLE_DEFINITION)gql"sv, DirectiveLocation::VARIABLE_DEFINITION },
142-
{ R"gql(INPUT_FIELD_DEFINITION)gql"sv, DirectiveLocation::INPUT_FIELD_DEFINITION }
123+
return std::array<std::pair<std::string_view, DirectiveLocation>, 19> {
124+
std::make_pair(R"gql(ENUM)gql"sv, DirectiveLocation::ENUM),
125+
std::make_pair(R"gql(FIELD)gql"sv, DirectiveLocation::FIELD),
126+
std::make_pair(R"gql(QUERY)gql"sv, DirectiveLocation::QUERY),
127+
std::make_pair(R"gql(UNION)gql"sv, DirectiveLocation::UNION),
128+
std::make_pair(R"gql(OBJECT)gql"sv, DirectiveLocation::OBJECT),
129+
std::make_pair(R"gql(SCALAR)gql"sv, DirectiveLocation::SCALAR),
130+
std::make_pair(R"gql(SCHEMA)gql"sv, DirectiveLocation::SCHEMA),
131+
std::make_pair(R"gql(MUTATION)gql"sv, DirectiveLocation::MUTATION),
132+
std::make_pair(R"gql(INTERFACE)gql"sv, DirectiveLocation::INTERFACE),
133+
std::make_pair(R"gql(ENUM_VALUE)gql"sv, DirectiveLocation::ENUM_VALUE),
134+
std::make_pair(R"gql(INPUT_OBJECT)gql"sv, DirectiveLocation::INPUT_OBJECT),
135+
std::make_pair(R"gql(SUBSCRIPTION)gql"sv, DirectiveLocation::SUBSCRIPTION),
136+
std::make_pair(R"gql(FRAGMENT_SPREAD)gql"sv, DirectiveLocation::FRAGMENT_SPREAD),
137+
std::make_pair(R"gql(INLINE_FRAGMENT)gql"sv, DirectiveLocation::INLINE_FRAGMENT),
138+
std::make_pair(R"gql(FIELD_DEFINITION)gql"sv, DirectiveLocation::FIELD_DEFINITION),
139+
std::make_pair(R"gql(ARGUMENT_DEFINITION)gql"sv, DirectiveLocation::ARGUMENT_DEFINITION),
140+
std::make_pair(R"gql(FRAGMENT_DEFINITION)gql"sv, DirectiveLocation::FRAGMENT_DEFINITION),
141+
std::make_pair(R"gql(VARIABLE_DEFINITION)gql"sv, DirectiveLocation::VARIABLE_DEFINITION),
142+
std::make_pair(R"gql(INPUT_FIELD_DEFINITION)gql"sv, DirectiveLocation::INPUT_FIELD_DEFINITION)
143143
};
144144
}
145145

samples/learn/schema/StarWarsSchema.cpp

Lines changed: 11 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@
1616
#include <sstream>
1717
#include <stdexcept>
1818
#include <string_view>
19-
#include <tuple>
19+
#include <utility>
2020
#include <vector>
2121

2222
using namespace std::literals;
@@ -35,9 +35,12 @@ learn::Episode ModifiedArgument<learn::Episode>::convert(const response::Value&
3535
throw service::schema_exception { { R"ex(not a valid Episode value)ex" } };
3636
}
3737

38-
const auto itr = s_valuesEpisode.find(value.get<std::string>());
38+
const auto [itr, itrEnd] = internal::find_sorted_map_key<internal::shorter_or_less>(
39+
s_valuesEpisode.begin(),
40+
s_valuesEpisode.end(),
41+
std::string_view { value.get<std::string>() });
3942

40-
if (itr == s_valuesEpisode.end())
43+
if (itr == itrEnd)
4144
{
4245
throw service::schema_exception { { R"ex(not a valid Episode value)ex" } };
4346
}
@@ -67,9 +70,12 @@ void ModifiedResult<learn::Episode>::validateScalar(const response::Value& value
6770
throw service::schema_exception { { R"ex(not a valid Episode value)ex" } };
6871
}
6972

70-
const auto itr = s_valuesEpisode.find(value.get<std::string>());
73+
const auto [itr, itrEnd] = internal::find_sorted_map_key<internal::shorter_or_less>(
74+
s_valuesEpisode.begin(),
75+
s_valuesEpisode.end(),
76+
std::string_view { value.get<std::string>() });
7177

72-
if (itr == s_valuesEpisode.end())
78+
if (itr == itrEnd)
7379
{
7480
throw service::schema_exception { { R"ex(not a valid Episode value)ex" } };
7581
}

samples/learn/schema/StarWarsSchema.h

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -44,10 +44,10 @@ constexpr auto getEpisodeValues() noexcept
4444
{
4545
using namespace std::literals;
4646

47-
return internal::string_view_map<Episode> {
48-
{ R"gql(JEDI)gql"sv, Episode::JEDI },
49-
{ R"gql(EMPIRE)gql"sv, Episode::EMPIRE },
50-
{ R"gql(NEW_HOPE)gql"sv, Episode::NEW_HOPE }
47+
return std::array<std::pair<std::string_view, Episode>, 3> {
48+
std::make_pair(R"gql(JEDI)gql"sv, Episode::JEDI),
49+
std::make_pair(R"gql(EMPIRE)gql"sv, Episode::EMPIRE),
50+
std::make_pair(R"gql(NEW_HOPE)gql"sv, Episode::NEW_HOPE)
5151
};
5252
}
5353

samples/today/nointrospection/TodaySchema.cpp

Lines changed: 11 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,7 @@
1717
#include <sstream>
1818
#include <stdexcept>
1919
#include <string_view>
20-
#include <tuple>
20+
#include <utility>
2121
#include <vector>
2222

2323
using namespace std::literals;
@@ -36,9 +36,12 @@ today::TaskState ModifiedArgument<today::TaskState>::convert(const response::Val
3636
throw service::schema_exception { { R"ex(not a valid TaskState value)ex" } };
3737
}
3838

39-
const auto itr = s_valuesTaskState.find(value.get<std::string>());
39+
const auto [itr, itrEnd] = internal::find_sorted_map_key<internal::shorter_or_less>(
40+
s_valuesTaskState.begin(),
41+
s_valuesTaskState.end(),
42+
std::string_view { value.get<std::string>() });
4043

41-
if (itr == s_valuesTaskState.end())
44+
if (itr == itrEnd)
4245
{
4346
throw service::schema_exception { { R"ex(not a valid TaskState value)ex" } };
4447
}
@@ -68,9 +71,12 @@ void ModifiedResult<today::TaskState>::validateScalar(const response::Value& val
6871
throw service::schema_exception { { R"ex(not a valid TaskState value)ex" } };
6972
}
7073

71-
const auto itr = s_valuesTaskState.find(value.get<std::string>());
74+
const auto [itr, itrEnd] = internal::find_sorted_map_key<internal::shorter_or_less>(
75+
s_valuesTaskState.begin(),
76+
s_valuesTaskState.end(),
77+
std::string_view { value.get<std::string>() });
7278

73-
if (itr == s_valuesTaskState.end())
79+
if (itr == itrEnd)
7480
{
7581
throw service::schema_exception { { R"ex(not a valid TaskState value)ex" } };
7682
}

samples/today/nointrospection/TodaySchema.h

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -46,11 +46,11 @@ constexpr auto getTaskStateValues() noexcept
4646
{
4747
using namespace std::literals;
4848

49-
return internal::string_view_map<TaskState> {
50-
{ R"gql(New)gql"sv, TaskState::New },
51-
{ R"gql(Started)gql"sv, TaskState::Started },
52-
{ R"gql(Complete)gql"sv, TaskState::Complete },
53-
{ R"gql(Unassigned)gql"sv, TaskState::Unassigned }
49+
return std::array<std::pair<std::string_view, TaskState>, 4> {
50+
std::make_pair(R"gql(New)gql"sv, TaskState::New),
51+
std::make_pair(R"gql(Started)gql"sv, TaskState::Started),
52+
std::make_pair(R"gql(Complete)gql"sv, TaskState::Complete),
53+
std::make_pair(R"gql(Unassigned)gql"sv, TaskState::Unassigned)
5454
};
5555
}
5656

samples/today/schema/TodaySchema.cpp

Lines changed: 11 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,7 @@
1717
#include <sstream>
1818
#include <stdexcept>
1919
#include <string_view>
20-
#include <tuple>
20+
#include <utility>
2121
#include <vector>
2222

2323
using namespace std::literals;
@@ -36,9 +36,12 @@ today::TaskState ModifiedArgument<today::TaskState>::convert(const response::Val
3636
throw service::schema_exception { { R"ex(not a valid TaskState value)ex" } };
3737
}
3838

39-
const auto itr = s_valuesTaskState.find(value.get<std::string>());
39+
const auto [itr, itrEnd] = internal::find_sorted_map_key<internal::shorter_or_less>(
40+
s_valuesTaskState.begin(),
41+
s_valuesTaskState.end(),
42+
std::string_view { value.get<std::string>() });
4043

41-
if (itr == s_valuesTaskState.end())
44+
if (itr == itrEnd)
4245
{
4346
throw service::schema_exception { { R"ex(not a valid TaskState value)ex" } };
4447
}
@@ -68,9 +71,12 @@ void ModifiedResult<today::TaskState>::validateScalar(const response::Value& val
6871
throw service::schema_exception { { R"ex(not a valid TaskState value)ex" } };
6972
}
7073

71-
const auto itr = s_valuesTaskState.find(value.get<std::string>());
74+
const auto [itr, itrEnd] = internal::find_sorted_map_key<internal::shorter_or_less>(
75+
s_valuesTaskState.begin(),
76+
s_valuesTaskState.end(),
77+
std::string_view { value.get<std::string>() });
7278

73-
if (itr == s_valuesTaskState.end())
79+
if (itr == itrEnd)
7480
{
7581
throw service::schema_exception { { R"ex(not a valid TaskState value)ex" } };
7682
}

samples/today/schema/TodaySchema.h

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -46,11 +46,11 @@ constexpr auto getTaskStateValues() noexcept
4646
{
4747
using namespace std::literals;
4848

49-
return internal::string_view_map<TaskState> {
50-
{ R"gql(New)gql"sv, TaskState::New },
51-
{ R"gql(Started)gql"sv, TaskState::Started },
52-
{ R"gql(Complete)gql"sv, TaskState::Complete },
53-
{ R"gql(Unassigned)gql"sv, TaskState::Unassigned }
49+
return std::array<std::pair<std::string_view, TaskState>, 4> {
50+
std::make_pair(R"gql(New)gql"sv, TaskState::New),
51+
std::make_pair(R"gql(Started)gql"sv, TaskState::Started),
52+
std::make_pair(R"gql(Complete)gql"sv, TaskState::Complete),
53+
std::make_pair(R"gql(Unassigned)gql"sv, TaskState::Unassigned)
5454
};
5555
}
5656

0 commit comments

Comments
 (0)