Qx v0.7
Qt Extensions Library
Loading...
Searching...
No Matches
qx-stringliteral.h
1#ifndef QX_STRINGLITERAL_H
2#define QX_STRINGLITERAL_H
3
4// Standard Library Includes
5#include <algorithm>
6#include <concepts>
7
8// Qt Includes
9#include <QLatin1String>
10
11// Intra-component Includes
13
14/* This base class is an implementation detail that makes it much easier (if not outright
15 * possible at all) to make concepts that need to work for all StringLiteral types while
16 * ignoring the size parameter N. Once Clang 19+ is common (see below todo), this won't
17 * be needed.
18 */
20namespace _QxPrivate
21{
22
23template<std::integral C>
24class StringLiteralBase {};
25
26template<typename O, size_t N1, size_t N2>
27constexpr auto concatNewStringLiteral(const typename O::data_t (&a)[N1], const typename O::data_t (&b)[N2])
28{
29 using C = typename O::data_t;
30 constexpr size_t L1 = N1 - 1;
31 constexpr size_t return_n = N1 + N2 - 1;
32 using result_t = typename O::template rebind<return_n>;
33
34 /* THIS ASSUMES THAT BOTH ARRAYS HAVE NULL TERMINATORS
35 * Using a buffer here results in needing to copy twice, but is much simpler than
36 * added a default ctor for each StringLiteral type, constructing, and copying in
37 * there directly. It's compile time so the inefficiency is basically a non-issue.
38 * Plus, this won't be an issue anyway once we can switch to aliases for the fixed
39 * width variants.
40 */
41 C buff[return_n];
42 std::copy_n(a, L1, buff); // a chars (without '/0')
43 std::copy_n(b, N2, buff + L1); // b chars (with '/0')
44 return result_t(buff);
45}
46
47}
49
50namespace Qx
51{
52
53// These concepts won't be needed either as per-above and todo.
54template<typename T>
56
57template<typename T, typename U>
61 std::same_as<typename T::data_t, typename U::data_t>;
62
63template<std::integral C, size_t N>
64class StringLiteral : public _QxPrivate::StringLiteralBase<C>
65{
66//-Aliases----------------------------------------------------------------------------------------------------------
67public:
68 using data_t = C;
69 using view_t = std::conditional_t<
70 std::is_same_v<C, char>,
71 QLatin1StringView,
72 std::conditional_t<
73 std::is_same_v<C, char16_t>,
74 QStringView,
75 void
76 >
77 >;
78
80 template<size_t M> using rebind = StringLiteral<C, M>; // Impl detail
82
83//-Class Variables---------------------------------------------------------------------------------------------------
84public:
85 static constexpr size_t size_v = N - 1;
86
87//-Instance Variables---------------------------------------------------------------------------------------------------
88public:
90 C _str[N]; // Must be public due to C++20 limitations
92
93//-Constructor----------------------------------------------------------------------------------------------------------
94public:
95 constexpr StringLiteral(const C (&str)[N]) { std::copy_n(str, N, _str); }
96
97//-Instance Functions----------------------------------------------------------------------------------------------------
98public:
99 constexpr C* data() const { return _str; }
100 constexpr size_t size() const { return N - 1; }
101 constexpr view_t view() const requires (!std::same_as<view_t, void>){ return view_t(*this); }
102 constexpr std::basic_string_view<C> std_view() const { return std::basic_string_view<C>(*this); }
103
104//-Operators--------------------------------------------------------------------------------------------------------
105public:
106 constexpr std::strong_ordering operator<=>(const StringLiteral& other) const = default;
107 constexpr bool operator==(const StringLiteral& other) const = default;
108 constexpr operator QLatin1StringView() const requires std::same_as<C, char> { return QLatin1StringView(_str, N - 1); }
109 constexpr operator QStringView() const requires std::same_as<C, char16_t > { return QStringView(_str, N - 1); }
110 constexpr operator std::basic_string_view<C>() const { return std::basic_string_view<C>(_str, N - 1); }
111};
112
113// Doc'ed here cause doxygen is finicky
119template<typename StringLiteralA, typename StringLiteralB>
120 requires compatible_string_literals<StringLiteralA, StringLiteralB>
121constexpr auto operator+(const StringLiteralA& a, const StringLiteralA& b)
122{
123 return _QxPrivate::concatNewStringLiteral<StringLiteralA>(a._str, b._str);
124}
125
126// Doc'ed here cause doxygen is finicky
132template<string_literal S, size_t N2>
133constexpr auto operator+(const S& a, const typename S::data_t (&b)[N2])
134{
135 return _QxPrivate::concatNewStringLiteral<S>(a._str, b);
136}
137
138// Doc'ed here cause doxygen is finicky
144template<size_t N1, string_literal S>
145constexpr auto operator+(const typename S::data_t (&a)[N1], const S& b)
146{
147 return _QxPrivate::concatNewStringLiteral<S>(a, b._str);
148}
149
150// Doc'ed here cause doxygen is finicky
156template<string_literal S>
157constexpr auto operator+(const S& a, typename S::data_t b) { return operator+(a, {b, '\0'}); }
158
159// Doc'ed here cause doxygen is finicky
165template<string_literal S>
166constexpr auto operator+(typename S::data_t a, const S& b) { return operator+({a, '\0'}, b); }
167
168/* TOOO: We use derivations here instead of template aliases as parameter deduction for aliases
169 * (what allows the parameter to deduce the character type and size just based on the
170 * type of string), P1814R0, as not implemented in Clang until 19!
171 *
172 * Once that version isn't that new, we can switch back to using aliases which should make the
173 * operator+() definition easier, as it will be able to look like (for example):
174 *
175 * template<std::integral C, size_t N1, size_t N2>
176 * constexpr auto operator+(const StringLiteral<C, N1>& a, const StringLiteral<C, N2>& b)
177 * {
178 * * Separate buffer is an extra copy, vs just making the result string and copying
179 * * into it directly, but this avoids the cruft of having to make these all friends
180 * * with the class and the speed loss is largely irrelevant since these are used
181 * * at compile time.
182 * *
183 * C buff[N1 + N2 - 1] ;
184 * std::copy_n(a._str, N1 - 1, buff); // a chars
185 * std::copy_n(b._str, N2, buff + (N1 - 1)); // b chars + '/0'
186 * return StringLiteral<C, N1 + N2 - 1>(buff);
187 * }
188 *
189 * instead of having to use the current constraint workaround that needs to allow derived types,
190 * which means we can remove a bunch of boilerplate like the 'rebind' alias
191 */
192template<size_t N>
193struct CStringLiteral final : public StringLiteral<char, N>
194{
195 constexpr CStringLiteral(const char (&str)[N]) : StringLiteral<char, N>(str) {} template<size_t M> using rebind = CStringLiteral<M>; // Impl detail
197};
198
199template<size_t N>
200struct WStringLiteral final : public StringLiteral<wchar_t, N>
201{
202 constexpr WStringLiteral(const wchar_t (&str)[N]) : StringLiteral<wchar_t, N>(str) {} template<size_t M> using rebind = WStringLiteral<M>; // Impl detail
204};
205
206template<size_t N>
207struct U8StringLiteral final : public StringLiteral<char8_t, N>
208{
209 constexpr U8StringLiteral(const char8_t (&str)[N]) : StringLiteral<char8_t, N>(str) {} template<size_t M> using rebind = U8StringLiteral<M>; // Impl detail
211};
212
213template<size_t N>
214struct U16StringLiteral final : public StringLiteral<char16_t, N>
215{
216 constexpr U16StringLiteral(const char16_t (&str)[N]) : StringLiteral<char16_t, N>(str) {} template<size_t M> using rebind = U16StringLiteral<M>; // Impl detail
218};
219
220template<size_t N>
221struct U32StringLiteral final : public StringLiteral<char32_t, N>
222{
223 constexpr U32StringLiteral(const char32_t (&str)[N]) : StringLiteral<char32_t, N>(str) {} template<size_t M> using rebind = U32StringLiteral<M>; // Impl detail
225};
226
227}
228
229#endif // QX_STRINGLITERAL_H
std::conditional_t< std::is_same_v< C, char >, QLatin1StringView, std::conditional_t< std::is_same_v< C, char16_t >, QStringView, void > > view_t
Definition qx-stringliteral.h:69
constexpr auto operator+(const S &a, typename S::data_t b)
Definition qx-stringliteral.h:157
constexpr bool operator==(const StringLiteral &other) const =default
static constexpr size_t size_v
Definition qx-stringliteral.h:85
constexpr auto operator+(typename S::data_t a, const S &b)
Definition qx-stringliteral.h:166
constexpr size_t size() const
Definition qx-stringliteral.h:100
constexpr std::basic_string_view< C > std_view() const
Definition qx-stringliteral.h:102
constexpr C * data() const
Definition qx-stringliteral.h:99
constexpr auto operator+(const StringLiteralA &a, const StringLiteralA &b)
Definition qx-stringliteral.h:121
constexpr view_t view() const
Definition qx-stringliteral.h:101
constexpr std::strong_ordering operator<=>(const StringLiteral &other) const =default
constexpr StringLiteral(const C(&str)[N])
Definition qx-stringliteral.h:95
C data_t
Definition qx-stringliteral.h:68
constexpr auto operator+(const typename S::data_t(&a)[N1], const S &b)
Definition qx-stringliteral.h:145
constexpr auto operator+(const S &a, const typename S::data_t(&b)[N2])
Definition qx-stringliteral.h:133
Specifies that two types are StringLiterals that use the same storage type.
Definition qx-stringliteral.h:58
Specifies that a type is a derivation of any specialization of a template.
Definition qx-concepts.h:516
Specifies that a type is a specialization or derivation of StringLiteral.
Definition qx-stringliteral.h:55
The Qx namespace is the main namespace through which all non-global functionality of the Qx library i...
Definition qx-abstracterror.cpp:13
The qx-concepts header file provides a library of general purpose concepts as an extension of the sta...
CStringLiteral acts like a typedef/alias for a StringLiteral that uses char as its storage type.
Definition qx-stringliteral.h:194
constexpr CStringLiteral(const char(&str)[N])
Definition qx-stringliteral.h:195
U16StringLiteral acts like a typedef/alias for a StringLiteral that uses char16_t as its storage type...
Definition qx-stringliteral.h:215
constexpr U16StringLiteral(const char16_t(&str)[N])
Definition qx-stringliteral.h:216
U32StringLiteral acts like a typedef/alias for a StringLiteral that uses char32_t as its storage type...
Definition qx-stringliteral.h:222
constexpr U32StringLiteral(const char32_t(&str)[N])
Definition qx-stringliteral.h:223
U8StringLiteral acts like a typedef/alias for a StringLiteral that uses char8_t as its storage type.
Definition qx-stringliteral.h:208
constexpr U8StringLiteral(const char8_t(&str)[N])
Definition qx-stringliteral.h:209
WStringLiteral acts like a typedef/alias for a StringLiteral that uses wchar_t as its storage type.
Definition qx-stringliteral.h:201
constexpr WStringLiteral(const wchar_t(&str)[N])
Definition qx-stringliteral.h:202