-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathStaticString.hpp
88 lines (86 loc) · 3.52 KB
/
StaticString.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
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
// require C++17 for CTAD
#pragma once
#include <cstddef>
#include <type_traits>
#include <utility>
template <std::size_t N> struct static_string {
char data[N + 1];
constexpr static std::size_t length = N;
constexpr auto &operator[](std::size_t i) { return data[i]; }
constexpr auto &operator[](std::size_t i) const { return data[i]; }
constexpr static_string() : data{0} {}
template <std::size_t... I>
constexpr static_string(const char (&str)[length + 1],
std::index_sequence<I...>)
: data{str[I]..., '\0'} {}
constexpr static_string(const char (&str)[length + 1])
: static_string{str, std::make_index_sequence<length>()} {}
template <typename... Ts>
constexpr static_string(const Ts &...str) : data{str...} {}
constexpr auto *begin() { return data; }
constexpr auto *begin() const { return data; }
constexpr auto *end() { return data + length; }
constexpr auto *end() const { return data + length; }
template <std::size_t begin, std::size_t count, std::size_t... I>
constexpr static_string<count> substr(std::index_sequence<I...>) const {
return static_string<count>{data[begin + I]..., '\0'};
}
template <std::size_t begin, std::size_t count,
typename = std::enable_if_t<(begin + count <= length)>>
constexpr static_string<count> substr() const {
return substr<begin, count>(std::make_index_sequence<count>());
}
};
template <std::size_t N>
static_string(const char (&)[N]) -> static_string<N - 1>;
template <std::size_t N1, std::size_t N2, std::size_t... I1, std::size_t... I2>
constexpr static_string<N1 + N2>
concat(const static_string<N1> &a, const static_string<N2> &b,
std::index_sequence<I1...>, std::index_sequence<I2...>) {
return static_string<N1 + N2>{a[I1]..., b[I2]..., '\0'};
}
template <std::size_t N1, std::size_t N2,
typename = std::enable_if_t<(N1 > 0 && N2 > 0)>>
constexpr static_string<N1 + N2> operator+(const static_string<N1> &a,
const static_string<N2> &b) {
return concat<N1, N2>(a, b, std::make_index_sequence<N1>(),
std::make_index_sequence<N2>());
}
constexpr static_string<0> operator+(const static_string<0> &a,
const static_string<0> &b) {
return "";
}
template <std::size_t N, typename = std::enable_if_t<(N > 0)>>
constexpr static_string<N> operator+(const static_string<N> &a,
const static_string<0> &b) {
return a;
}
template <std::size_t N, typename = std::enable_if_t<(N > 0)>>
constexpr static_string<N> operator+(const static_string<0> &a,
const static_string<N> &b) {
return b;
}
template <std::size_t I, std::size_t N>
constexpr bool same(const static_string<N> &a, const static_string<N> &b) {
return a[I] == b[I];
}
template <std::size_t N, std::size_t... I>
constexpr bool same(const static_string<N> &a, const static_string<N> &b,
std::index_sequence<I...>) {
return (same<I>(a, b) && ...);
}
template <std::size_t N>
constexpr bool operator==(const static_string<N> &a,
const static_string<N> &b) {
return same(a, b, std::make_index_sequence<N>());
}
template <std::size_t N1, std::size_t N2>
constexpr bool operator==(const static_string<N1> &a,
const static_string<N2> &b) {
return false;
}
template <std::size_t N1, std::size_t N2>
constexpr bool operator!=(const static_string<N1> &a,
const static_string<N2> &b) {
return !(a == b);
}