9#include <unordered_set>
11USERVER_NAMESPACE_BEGIN
15namespace impl::projected_set {
17template <
typename Raw,
auto Projection>
18using ProjectionResult = std::decay_t<std::invoke_result_t<
decltype(Projection),
const Raw&>>;
20template <
typename Raw,
auto Projection,
typename ResultHash>
21using DefaultedResultHash =
22 std::conditional_t<std::is_void_v<ResultHash>, std::hash<ProjectionResult<Raw, Projection>>, ResultHash>;
24template <
typename Raw,
auto Projection,
typename ResultHash>
25struct Hash :
public DefaultedResultHash<Raw, Projection, ResultHash> {
26 using is_transparent [[maybe_unused]] =
void;
27 using Base = DefaultedResultHash<Raw, Projection, ResultHash>;
29 auto operator()(
const Raw& value)
const noexcept {
return Base::operator()(std::invoke(Projection, value)); }
31 using Base::operator();
34template <
typename Raw,
auto Projection,
typename ResultCompare>
35struct Compare :
public ResultCompare {
36 using is_transparent [[maybe_unused]] =
void;
38 auto operator()(
const Raw& lhs,
const Raw& rhs)
const noexcept {
39 return ResultCompare::operator()(std::invoke(Projection, lhs), std::invoke(Projection, rhs));
43 auto operator()(
const Raw& lhs,
const T& rhs)
const noexcept {
44 return ResultCompare::operator()(std::invoke(Projection, lhs), rhs);
48 auto operator()(
const T& lhs,
const Raw& rhs)
const noexcept {
49 return ResultCompare::operator()(lhs, std::invoke(Projection, rhs));
52 template <
typename T,
typename U>
53 auto operator()(
const T& lhs,
const U& rhs)
const noexcept {
54 return ResultCompare::operator()(lhs, rhs);
58template <
typename Set,
typename Value>
59void DoInsert(Set& set, Value&& value) {
60 const auto [iter, success] = set.insert(std::forward<Value>(value));
62 using SetValue = std::decay_t<
decltype(*iter)>;
66 const_cast<SetValue&>(*iter) = std::forward<Value>(value);
99template <
typename Container,
typename Value>
101 impl::projected_set::DoInsert(set, std::forward<Value>(value));
104namespace impl::projected_set {
122 const ProjectedUnorderedSet<V1, P1, H1, E1, A1>& lhs,
123 const ProjectedUnorderedSet<V2, P2, H2, E2, A2>& rhs
138 const ProjectedUnorderedSet<V1, P1, H1, E1, A1>& lhs,
139 const ProjectedUnorderedSet<V2, P2, H2, E2, A2>& rhs
142template <
typename V1,
const auto& P1,
typename C1,
typename A1,
typename V2,
const auto& P2,
typename C2,
typename A2>
143void operator==(
const ProjectedSet<V1, P1, C1, A1>& lhs,
const ProjectedSet<V2, P2, C2, A2>& rhs) =
delete;
145template <
typename V1,
const auto& P1,
typename C1,
typename A1,
typename V2,
const auto& P2,
typename C2,
typename A2>
146void operator!=(
const ProjectedSet<V1, P1, C1, A1>& lhs,
const ProjectedSet<V2, P2, C2, A2>& rhs) =
delete;