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"
8template <
typename T,
typename P = package_t<T>, enable_if_t<is_packaged_v<T> && is_base_of_v<i
stringify<P>, P>,
int> = 0>
9MSTL_NODISCARD MSTL_CONSTEXPR20
string to_string(
const T& value) {
13MSTL_NODISCARD MSTL_CONSTEXPR20
string to_string(
nullptr_t) {
17template <
typename T, enable_if_t<is_po
inter_v<T> && !is_c
string_v<T>,
int> = 0>
18MSTL_NODISCARD MSTL_CONSTEXPR20
string to_string(
const T& x) {
19 return _MSTL address_string(x);
25template <
typename Collector>
26MSTL_NODISCARD MSTL_CONSTEXPR20
string collector_to_string(
const Collector& c) {
32 result += to_string(*iter);
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);
46template <
typename T, enable_if_t<is_unbounded_array_v<T>,
int> = 0>
47MSTL_NODISCARD MSTL_CONSTEXPR20
string to_string(
const T&) {
51template <
typename T, enable_if_t<is_bounded_array_v<T> && !is_c
string_v<T>,
int> = 0>
52MSTL_NODISCARD MSTL_CONSTEXPR20
string to_string(
const T& x) {
53 return _INNER collector_to_string(x);
58template <
typename T, T N>
59constexpr const char* __get_enum_name_raw() {
60#ifdef MSTL_COMPILER_MSVC__
63 return __PRETTY_FUNCTION__;
67template <s
size_t Beg, s
size_t End,
typename F, enable_if_t<Beg == End,
int> = 0>
68MSTL_CONSTEXPR20
void static_for(
const F&) {}
70template <s
size_t Beg, s
size_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);
77struct __enum_name_functor {
83 __enum_name_functor(UT n,
string &s) : n(n), s(s) {}
86 MSTL_CONSTEXPR20
void call()
const {
88 s = __get_enum_name_raw<T, static_cast<T>(I)>();
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");
100 _INNER static_for<static_cast<UT>(Beg),
static_cast<UT
>(End) + 1>(
101 _INNER __enum_name_functor<T>(
static_cast<UT
>(n), s));
105#ifdef MSTL_COMPILER_MSVC__
106 size_t pos = s.find(
',');
108 size_t pos2 = s.find(
'>', pos);
110 size_t pos = s.find(
"N = ");
112 size_t pos2 = s.find_first_of(
";]", pos);
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);
123MSTL_CONSTEXPR20
string enum_name(T n) {
124 return _MSTL enum_name<T, static_cast<T>(0),
static_cast<T
>(256)>(n);
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);
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() +
")";
137template <
typename IfEmpty,
typename T>
139 return to_string(obj.
value);
142template <
typename IfEmpty,
typename T>
144 return "{ " + to_string(obj.
value) +
", " + to_string(obj.no_compressed) +
" }";
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) +
" }";
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) {
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);
166template <
typename... UArgs, enable_if_t<sizeof...(UArgs) == 0,
int> = 0>
167MSTL_CONSTEXPR20
string __to_string_tuple_dispatch(
const tuple<UArgs...>&) {
171template <
typename... UArgs,
enable_if_t<
sizeof...(UArgs) != 0,
int> = 0>
172MSTL_CONSTEXPR20
string __to_string_tuple_dispatch(
const tuple<UArgs...>& t) {
175 _INNER __to_string_tuple_elements<decltype(t), 0>(t, result);
182template <
typename... Args>
183MSTL_NODISCARD MSTL_CONSTEXPR20
string to_string(
const tuple<Args...>& t) {
184 return _INNER __to_string_tuple_dispatch(t);
187MSTL_NODISCARD MSTL_CONSTEXPR20
string to_string(
const bstring& x) {
188 return string(x.begin(), x.end());
191MSTL_NODISCARD MSTL_CONSTEXPR20 bstring to_bstring(
const string& x) {
192 return bstring(x.begin(), x.end());
195MSTL_NODISCARD MSTL_CONSTEXPR20 bstring to_bstring(
const string_view x) {
196 return bstring(x.begin(), x.end());
200#ifndef MSTL_STANDARD_17__
204string to_string_concat(T&& t) {
207template <
typename First,
typename... Rest>
208string to_string_concat(First&& first, Rest&&... rest) {
213template <
typename... Args,
enable_if_t<(
sizeof...(Args) > 1),
int> = 0>
214MSTL_NODISCARD
string to_string(Args&&... args) {
219template <
typename... Args,
enable_if_t<(
sizeof...(Args) > 1),
int> = 0>
220MSTL_NODISCARD MSTL_CONSTEXPR20
string to_string(Args&&... args) {
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);
240template <
typename CharT,
typename UT, enable_if_t<sizeof(UT) <= 4,
int> = 0>
241constexpr
void __u
int_to_buff_aux(CharT*, UT&) noexcept {}
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__
249 _INNER __uint_to_buff_aux(riter, ux);
250 auto holder =
static_cast<uint32_t>(ux);
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));
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) {
262 CharT*
const buffer_end = buffer + 21;
263 CharT* rnext = buffer_end;
265 const auto unsigned_x =
static_cast<UT
>(x);
267 rnext =
_INNER __uint_to_buff(rnext,
static_cast<UT
>(0 - unsigned_x));
270 rnext =
_INNER __uint_to_buff(rnext, unsigned_x);
272 const size_t count = buffer_end - rnext;
273 return basic_string<CharT>(rnext,
count);
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) {
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);
285MSTL_CONSTEXPR20
string __uint_to_string_base(
uint64_t value,
const int base,
const bool uppercase) {
290 constexpr auto digits_lower =
"0123456789abcdef";
291 constexpr auto digits_upper =
"0123456789ABCDEF";
292 const auto digits = uppercase ? digits_upper : digits_lower;
304MSTL_NODISCARD MSTL_CONSTEXPR20
string __int_to_string_dispatch(
const T x) {
305 return _INNER __int_to_string<char>(x);
309MSTL_NODISCARD MSTL_CONSTEXPR20
string __int_to_string_dispatch(
const T x) {
310 return _INNER __uint_to_string<char>(x);
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) {
319 if (x == inf || x == -inf) {
320 return (x < 0) ? basic_string<CharT>{
"-inf"} : basic_string<CharT>{
"inf"};
323 basic_string<CharT> result;
330 if (precision < 0) precision = 0;
332 bool use_scientific =
false;
333 if (force_scientific) {
334 use_scientific =
true;
335 }
else if (force_fixed) {
336 use_scientific =
false;
338 use_scientific = (x >= 1e6 || (x > 0 && x < 1e-4));
341 if (use_scientific) {
360 auto integer_part =
static_cast<uint64_t>(x);
361 T fractional_part = x - integer_part;
363 result +=
_INNER __uint_to_string<CharT>(integer_part);
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;
380 exponent = -exponent;
386 result +=
_INNER __uint_to_string<CharT>(
static_cast<uint64_t>(exponent));
389 auto integer_part =
static_cast<uint64_t>(x);
390 T fractional_part = x - integer_part;
392 result +=
_INNER __uint_to_string<CharT>(integer_part);
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;
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);
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);
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);
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);
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);
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的便捷别名