-
Notifications
You must be signed in to change notification settings - Fork 33
/
span_adl.hpp
47 lines (42 loc) · 1.31 KB
/
span_adl.hpp
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
/**
* Copyright Quadrivium LLC
* All Rights Reserved
* SPDX-License-Identifier: Apache-2.0
*/
#pragma once
#include <algorithm>
#include <cstdint>
#include <cstring>
#include <qtils/cxx20/lexicographical_compare_three_way.hpp>
#include <span>
// `std::span` doesn't have comparison operator functions.
// Can't add function to neither `std::span` nor `namespace std`.
// `SpanAdl{span}` wraps span and allows writing functions for `SpanAdl`.
// `SpanAdl` overload will be selected by ADL.
template <typename T>
struct SpanAdl {
std::span<T> v;
};
template <typename T>
SpanAdl(T &&t) -> SpanAdl<typename decltype(std::span{t})::element_type>;
template <typename T>
auto operator<=>(const SpanAdl<T> &l_, const auto &r_)
requires(requires { std::span<const T>{r_}; })
{
auto &[l] = l_;
std::span r{r_};
if constexpr (std::is_same_v<std::remove_cvref_t<T>, uint8_t>) {
auto n = std::min(l.size(), r.size());
auto c = std::memcmp(l.data(), r.data(), n) <=> 0;
return c != 0 ? c : l.size() <=> r.size();
}
return qtils::cxx20::lexicographical_compare_three_way(
l.begin(), l.end(), r.begin(), r.end());
}
template <typename T>
bool operator==(const SpanAdl<T> &l_, const auto &r_)
requires(requires { std::span<const T>{r_}; })
{
std::span r{r_};
return l_.v.size() == r.size() and (l_ <=> r) == 0;
}