MSTL 1.4.0
A Modern C++ Library with extended functionality, web components, and utility libraries
载入中...
搜索中...
未找到
to_string.hpp
1#ifndef MSTL_CORE_STRING_TO_STRING_HPP__
2#define MSTL_CORE_STRING_TO_STRING_HPP__
3#include "../interface/istringify.hpp"
5#include "character.hpp"
7
8template <typename T, typename P = package_t<T>, enable_if_t<is_packaged_v<T> && is_base_of_v<istringify<P>, P>, int> = 0>
9MSTL_NODISCARD MSTL_CONSTEXPR20 string to_string(const T& value) {
10 return to_string(package_t<T>(value));
11}
12
13MSTL_NODISCARD MSTL_CONSTEXPR20 string to_string(nullptr_t) {
14 return {"nullptr"};
15}
16
17template <typename T, enable_if_t<is_pointer_v<T> && !is_cstring_v<T>, int> = 0>
18MSTL_NODISCARD MSTL_CONSTEXPR20 string to_string(const T& x) {
19 return _MSTL address_string(x);
20}
21
22
24
25template <typename Collector>
26MSTL_NODISCARD MSTL_CONSTEXPR20 string collector_to_string(const Collector& c) {
27 if (_MSTL empty(c)) return {"[]"};
28 string result;
29 result += "[ ";
30 for (auto iter = _MSTL cbegin(c); iter != _MSTL cend(c); ++iter) {
31 if (iter != _MSTL cbegin(c)) result += ", ";
32 result += to_string(*iter);
33 }
34 result += " ]";
35 return result;
36}
37
39
40template <typename T, enable_if_t<is_base_of_v<icollector<T>, T>, int> = 0>
41MSTL_NODISCARD MSTL_CONSTEXPR20 string to_string(const T& x) {
42 return _INNER collector_to_string(x);
43}
44
45
46template <typename T, enable_if_t<is_unbounded_array_v<T>, int> = 0>
47MSTL_NODISCARD MSTL_CONSTEXPR20 string to_string(const T&) {
48 return {"[]"};
49}
50
51template <typename T, enable_if_t<is_bounded_array_v<T> && !is_cstring_v<T>, int> = 0>
52MSTL_NODISCARD MSTL_CONSTEXPR20 string to_string(const T& x) {
53 return _INNER collector_to_string(x);
54}
55
57
58template <typename T, T N>
59constexpr const char* __get_enum_name_raw() {
60#ifdef MSTL_COMPILER_MSVC__
61 return __FUNCSIG__;
62#else
63 return __PRETTY_FUNCTION__;
64#endif
65}
66
67template <ssize_t Beg, ssize_t End, typename F, enable_if_t<Beg == End, int> = 0>
68MSTL_CONSTEXPR20 void static_for(const F&) {}
69
70template <ssize_t Beg, ssize_t End, typename F, enable_if_t<Beg != End, int> = 0>
71MSTL_CONSTEXPR20 void static_for(const F& func) {
72 func.template call<Beg>();
73 _INNER static_for<Beg + 1, End>(func);
74}
75
76template <typename T>
77struct __enum_name_functor {
78 using UT = underlying_type_t<T>;
79
80 UT n;
81 string &s;
82
83 __enum_name_functor(UT n, string &s) : n(n), s(s) {}
84
85 template <UT I>
86 MSTL_CONSTEXPR20 void call() const {
87 if (n == I) {
88 s = __get_enum_name_raw<T, static_cast<T>(I)>();
89 }
90 }
91};
92
94
95template <typename T, T Beg, T End>
96MSTL_CONSTEXPR20 string enum_name(T n) {
97 static_assert(is_enum_v<T>, "T must be an enumeration");
98 string s;
99 using UT = underlying_type_t<T>;
100 _INNER static_for<static_cast<UT>(Beg), static_cast<UT>(End) + 1>(
101 _INNER __enum_name_functor<T>(static_cast<UT>(n), s));
102 if (s.empty()) {
103 return "";
104 }
105#ifdef MSTL_COMPILER_MSVC__
106 size_t pos = s.find(',');
107 pos += 1;
108 size_t pos2 = s.find('>', pos);
109#else
110 size_t pos = s.find("N = ");
111 pos += 4;
112 size_t pos2 = s.find_first_of(";]", pos);
113#endif
114 s = s.substr(pos, pos2 - pos);
115 const size_t pos3 = s.rfind("::");
116 if (pos3 != s.npos) {
117 s = s.substr(pos3 + 2);
118 }
119 return s;
120}
121
122template <typename T>
123MSTL_CONSTEXPR20 string enum_name(T n) {
124 return _MSTL enum_name<T, static_cast<T>(0), static_cast<T>(256)>(n);
125}
126
127template <typename T, enable_if_t<is_enum_v<T>, int> = 0>
128MSTL_NODISCARD MSTL_CONSTEXPR20 string to_string(const T& x) {
129 return _MSTL enum_name(x);
130}
131
132template <typename T, enable_if_t<is_base_of_v<_MSTL exception, T>, int> = 0>
133MSTL_NODISCARD MSTL_CONSTEXPR20 string to_string(const T& obj) {
134 return string(obj.type()) + "(" + obj.what() + ")";
135}
136
137template <typename IfEmpty, typename T>
138MSTL_NODISCARD MSTL_CONSTEXPR20 string to_string(const compressed_pair<IfEmpty, T, true>& obj) {
139 return to_string(obj.value);
140}
141
142template <typename IfEmpty, typename T>
143MSTL_NODISCARD MSTL_CONSTEXPR20 string to_string(const compressed_pair<IfEmpty, T, false>& obj) {
144 return "{ " + to_string(obj.value) + ", " + to_string(obj.no_compressed) + " }";
145}
146
147template <typename T1, typename T2>
148MSTL_NODISCARD MSTL_CONSTEXPR20 string to_string(const pair<T1, T2>& obj) {
149 return "{ " + to_string(obj.first) + ", " + to_string(obj.second) + " }";
150}
151
152
154
155template <typename Tuple, size_t I, enable_if_t<I == tuple_size_v<Tuple> - 1, int> = 0>
156MSTL_CONSTEXPR20 void __to_string_tuple_elements(const Tuple& t, string& result) {
157 result += to_string(_MSTL get<I>(t));
158}
159
160template <typename Tuple, size_t I, enable_if_t<I < tuple_size_v<Tuple> - 1, int> = 0>
161MSTL_CONSTEXPR20 void __to_string_tuple_elements(const Tuple& t, string& result) {
162 result += to_string(_MSTL get<I>(t)) + ", ";
163 _INNER __to_string_tuple_elements<Tuple, I + 1>(t, result);
164}
165
166template <typename... UArgs, enable_if_t<sizeof...(UArgs) == 0, int> = 0>
167MSTL_CONSTEXPR20 string __to_string_tuple_dispatch(const tuple<UArgs...>&) {
168 return {"()"};
169}
170
171template <typename... UArgs, enable_if_t<sizeof...(UArgs) != 0, int> = 0>
172MSTL_CONSTEXPR20 string __to_string_tuple_dispatch(const tuple<UArgs...>& t) {
173 string result;
174 result += "( ";
175 _INNER __to_string_tuple_elements<decltype(t), 0>(t, result);
176 result += " )";
177 return result;
178}
179
181
182template <typename... Args>
183MSTL_NODISCARD MSTL_CONSTEXPR20 string to_string(const tuple<Args...>& t) {
184 return _INNER __to_string_tuple_dispatch(t);
185}
186
187MSTL_NODISCARD MSTL_CONSTEXPR20 string to_string(const bstring& x) {
188 return string(x.begin(), x.end());
189}
190
191MSTL_NODISCARD MSTL_CONSTEXPR20 bstring to_bstring(const string& x) {
192 return bstring(x.begin(), x.end());
193}
194
195MSTL_NODISCARD MSTL_CONSTEXPR20 bstring to_bstring(const string_view x) {
196 return bstring(x.begin(), x.end());
197}
198
199
200#ifndef MSTL_STANDARD_17__
201
203template <typename T>
204string to_string_concat(T&& t) {
205 return to_string(_MSTL forward<T>(t));
206}
207template <typename First, typename... Rest>
208string to_string_concat(First&& first, Rest&&... rest) {
209 return to_string(_MSTL forward<First>(first)) + to_string_concat(_MSTL forward<Rest>(rest)...);
210}
212
213template <typename... Args, enable_if_t<(sizeof...(Args) > 1), int> = 0>
214MSTL_NODISCARD string to_string(Args&&... args) {
215 return _INNER to_string_concat(_MSTL forward<Args>(args)...);
216}
217
218#else
219template <typename... Args, enable_if_t<(sizeof...(Args) > 1), int> = 0>
220MSTL_NODISCARD MSTL_CONSTEXPR20 string to_string(Args&&... args) {
221 return (to_string(_MSTL forward<Args>(args)) + ...);
222}
223#endif
224
225
227
228#ifndef MSTL_DATA_BUS_WIDTH_64__
229template <typename CharT, typename UT, enable_if_t<(sizeof(UT) > 4), int> = 0>
230constexpr void __uint_to_buff_aux(CharT* riter, UT& ux) noexcept {
231 while (ux > static_cast<UT>(0xFFFFFFFFU)) {
232 auto chunk = static_cast<uint32_t>(ux % static_cast<UT>(1000000000));
233 ux /= static_cast<UT>(1000000000);
234 for (int idx = 0; idx != 9; ++idx) {
235 *--riter = static_cast<CharT>('0' + chunk % 10);
236 chunk /= 10;
237 }
238 }
239}
240template <typename CharT, typename UT, enable_if_t<sizeof(UT) <= 4, int> = 0>
241constexpr void __uint_to_buff_aux(CharT*, UT&) noexcept {}
242#endif // MSTL_DATA_BUS_WIDTH_64__
243
244template <typename CharT, typename UT, enable_if_t<is_unsigned<UT>::value, int> = 0>
245MSTL_NODISCARD constexpr CharT* __uint_to_buff(CharT* riter, UT ux) noexcept {
246#ifdef MSTL_DATA_BUS_WIDTH_64__
247 UT holder = ux;
248#else
249 _INNER __uint_to_buff_aux(riter, ux);
250 auto holder = static_cast<uint32_t>(ux);
251#endif
252 do {
253 *--riter = static_cast<CharT>('0' + holder % static_cast<UT>(10));
254 holder /= static_cast<UT>(10);
255 } while (static_cast<UT>(holder) != static_cast<UT>(0));
256 return riter;
257}
258
259template <typename CharT, typename T, enable_if_t<is_integral<T>::value, int> = 0>
260MSTL_NODISCARD MSTL_CONSTEXPR20 basic_string<CharT> __int_to_string(const T x) {
261 CharT buffer[21];
262 CharT* const buffer_end = buffer + 21;
263 CharT* rnext = buffer_end;
264 using UT = make_unsigned_t<T>;
265 const auto unsigned_x = static_cast<UT>(x);
266 if (x < 0) {
267 rnext = _INNER __uint_to_buff(rnext, static_cast<UT>(0 - unsigned_x));
268 *--rnext = '-';
269 } else {
270 rnext = _INNER __uint_to_buff(rnext, unsigned_x);
271 }
272 const size_t count = buffer_end - rnext;
273 return basic_string<CharT>(rnext, count);
274}
275
276template <typename CharT, typename T, enable_if_t<conjunction<is_integral<T>, is_unsigned<T>>::value, int> = 0>
277MSTL_NODISCARD MSTL_CONSTEXPR20 basic_string<CharT> __uint_to_string(T x) {
278 CharT buffer[21];
279 CharT* const buffer_end = buffer + 21;
280 CharT* const rnext = _INNER __uint_to_buff(buffer_end, x);
281 const size_t count = buffer_end - rnext;
282 return basic_string<CharT>(rnext, count);
283}
284
285MSTL_CONSTEXPR20 string __uint_to_string_base(uint64_t value, const int base, const bool uppercase) {
286 if (value == 0) {
287 return "0";
288 }
289 string result;
290 constexpr auto digits_lower = "0123456789abcdef";
291 constexpr auto digits_upper = "0123456789ABCDEF";
292 const auto digits = uppercase ? digits_upper : digits_lower;
293 while (value > 0) {
294 const uint64_t remainder = value % base;
295 value /= base;
296 result.push_back(digits[remainder]);
297 }
298 result.reverse();
299 return result;
300}
301
302template <typename T, enable_if_t<
303 disjunction_v<conjunction<is_standard_integral<T>, is_signed<T>>, is_same<T, signed char>>, int> = 0>
304MSTL_NODISCARD MSTL_CONSTEXPR20 string __int_to_string_dispatch(const T x) {
305 return _INNER __int_to_string<char>(x);
306}
307template <typename T, enable_if_t<
308 disjunction_v<conjunction<is_standard_integral<T>, is_unsigned<T>>, is_same<T, unsigned char>>, int> = 0>
309MSTL_NODISCARD MSTL_CONSTEXPR20 string __int_to_string_dispatch(const T x) {
310 return _INNER __uint_to_string<char>(x);
311}
312
313
314template <typename CharT, typename T, enable_if_t<is_floating_point<T>::value, int> = 0>
315MSTL_NODISCARD MSTL_CONSTEXPR20 basic_string<CharT> __float_to_string_with_precision(
316 T x, int precision = 6, const bool force_scientific = false, const bool force_fixed = false) {
317 if (x == numeric_traits<T>::quiet_nan()) return basic_string<CharT>{"nan"};
318 constexpr T inf = numeric_traits<T>::infinity();
319 if (x == inf || x == -inf) {
320 return (x < 0) ? basic_string<CharT>{"-inf"} : basic_string<CharT>{"inf"};
321 }
322
323 basic_string<CharT> result;
324
325 if (x < 0) {
326 result += '-';
327 x = -x;
328 }
329
330 if (precision < 0) precision = 0;
331
332 bool use_scientific = false;
333 if (force_scientific) {
334 use_scientific = true;
335 } else if (force_fixed) {
336 use_scientific = false;
337 } else {
338 use_scientific = (x >= 1e6 || (x > 0 && x < 1e-4));
339 }
340
341 if (use_scientific) {
342 int exponent = 0;
343
344 if (x == 0) {
345 exponent = 0;
346 } else {
347 if (x >= 1) {
348 while (x >= 10) {
349 x /= 10;
350 ++exponent;
351 }
352 } else {
353 while (x < 1) {
354 x *= 10;
355 --exponent;
356 }
357 }
358 }
359
360 auto integer_part = static_cast<uint64_t>(x);
361 T fractional_part = x - integer_part;
362
363 result += _INNER __uint_to_string<CharT>(integer_part);
364
365 if (precision > 0) {
366 result += '.';
367 for (int i = 0; i < precision; ++i) {
368 fractional_part *= 10;
369 auto digit = static_cast<int>(fractional_part);
370 result += static_cast<CharT>('0' + digit);
371 fractional_part -= digit;
372 }
373 }
374
375 result += 'e';
376 if (exponent >= 0) {
377 result += '+';
378 } else {
379 result += '-';
380 exponent = -exponent;
381 }
382
383 if (exponent < 10) {
384 result += '0';
385 }
386 result += _INNER __uint_to_string<CharT>(static_cast<uint64_t>(exponent));
387
388 } else {
389 auto integer_part = static_cast<uint64_t>(x);
390 T fractional_part = x - integer_part;
391
392 result += _INNER __uint_to_string<CharT>(integer_part);
393
394 if (precision > 0) {
395 result += '.';
396 for (int i = 0; i < precision; ++i) {
397 fractional_part *= 10;
398 auto digit = static_cast<int>(fractional_part);
399 result += static_cast<CharT>('0' + digit);
400 fractional_part -= digit;
401 }
402 }
403 }
404
405 return result;
406}
407
408template <typename CharT, typename T, enable_if_t<is_floating_point<T>::value, int> = 0>
409MSTL_NODISCARD MSTL_CONSTEXPR20 basic_string<CharT> __float_to_string(T x) {
410 return _INNER __float_to_string_with_precision<CharT>(x, 6, false, false);
411}
412
414
415template <typename T, enable_if_t<is_floating_point<T>::value, int> = 0>
416MSTL_NODISCARD MSTL_CONSTEXPR20 string to_string_with_precision(T x, int precision, bool scientific = false) {
417 return _INNER __float_to_string_with_precision<char>(x, precision, scientific, scientific);
418}
419
420template <typename T, enable_if_t<is_floating_point<T>::value, int> = 0>
421MSTL_NODISCARD MSTL_CONSTEXPR20 string to_string_general(T x, int precision = 6) {
422 return _INNER __float_to_string_with_precision<char>(x, precision, false, false);
423}
424
425template <typename T, enable_if_t<is_floating_point<T>::value, int> = 0>
426MSTL_NODISCARD MSTL_CONSTEXPR20 string to_string_fixed(T x, int precision = 6) {
427 return _INNER __float_to_string_with_precision<char>(x, precision, false, true);
428}
429
430template <typename T, enable_if_t<is_floating_point<T>::value, int> = 0>
431MSTL_NODISCARD MSTL_CONSTEXPR20 string to_string_scientific(T x, int precision = 6) {
432 return _INNER __float_to_string_with_precision<char>(x, precision, true, false);
433}
434
436#endif // MSTL_CORE_STRING_TO_STRING_HPP__
static MSTL_NODISCARD constexpr T infinity() noexcept
获取正无穷大表示
static MSTL_NODISCARD constexpr T quiet_nan() noexcept
获取安静nan表示
MSTL_NODISCARD constexpr T && forward(remove_reference_t< T > &x) noexcept
完美转发左值
MSTL_ALWAYS_INLINE enable_if_t< is_void_v< T >, future_result_t< T > > get(future< T > &f)
通用future结果获取函数
typename package< T >::type package_t
package的便捷别名
typename underlying_type< T >::type underlying_type_t
underlying_type的便捷别名
unsigned int uint32_t
32位无符号整数类型
unsigned long long uint64_t
64位无符号整数类型
decltype(nullptr) nullptr_t
空指针类型
constexpr iter_difference_t< Iterator > count(Iterator first, Iterator last, const T &value)
统计范围内等于指定值的元素数量
MSTL_CONST_FUNCTION MSTL_CONSTEXPR14 decimal_t remainder(const decimal_t x, const decimal_t y) noexcept
计算余数
#define _MSTL
全局命名空间MSTL前缀
#define MSTL_END_INNER__
结束inner命名空间
#define _INNER
inner命名空间前缀
#define MSTL_END_NAMESPACE__
结束全局命名空间MSTL
#define MSTL_BEGIN_NAMESPACE__
开始全局命名空间MSTL
#define MSTL_BEGIN_INNER__
开始inner命名空间
typename make_unsigned< T >::type make_unsigned_t
make_unsigned的便捷别名
MSTL_NODISCARD MSTL_ALWAYS_INLINE constexpr bool empty(const Container &cont) noexcept(noexcept(cont.empty()))
检查容器是否为空
MSTL_NODISCARD MSTL_ALWAYS_INLINE constexpr decltype(auto) cend(const Container &cont) noexcept(noexcept(cont.cend()))
获取const容器的const结束迭代器
MSTL_NODISCARD MSTL_ALWAYS_INLINE constexpr decltype(auto) cbegin(const Container &cont) noexcept(noexcept(cont.cbegin()))
获取const容器的const起始迭代器
typename enable_if< Test, T >::type enable_if_t
enable_if的便捷别名
MSTL集合器接口
压缩对主模板,使用EBCO优化
判断两个类型是否相同
判断类型是否为有符号类型
判断类型是否为无符号类型
存储两个值的元组对
T2 second
第二个元素
T1 first
第一个元素