1#ifndef NEFORCE_CORE_STRING_TO_STRING_HPP__
2#define NEFORCE_CORE_STRING_TO_STRING_HPP__
18NEFORCE_BEGIN_NAMESPACE__
34template <
typename T,
typename P = package_t<T>,
35 enable_if_t<is_packaged_v<T> && is_base_of_v<i
stringify<P>, P>,
int> = 0>
36NEFORCE_NODISCARD NEFORCE_CONSTEXPR20
string to_string(
const T& value) {
55template <
typename T, enable_if_t<is_po
inter_v<T> && !is_c
string_v<T>,
int> = 0>
56NEFORCE_NODISCARD NEFORCE_CONSTEXPR20
string to_string(
const T& ptr) {
63template <
typename Collector>
64NEFORCE_NODISCARD NEFORCE_CONSTEXPR20
string collector_to_string(
const Collector& c) {
65 if (_NEFORCE
empty(c)) {
73 for (
auto iter =
begin; iter != _NEFORCE
cend(c); ++iter) {
93template <
typename T, enable_if_t<is_base_of_v<icollector<T>, T>,
int> = 0>
94NEFORCE_NODISCARD NEFORCE_CONSTEXPR20
string to_string(
const T& c) {
95 return inner::collector_to_string(c);
98template <
typename T, enable_if_t<is_base_of_v<ranges::view_base<T>, T>,
int> = 0>
99NEFORCE_NODISCARD NEFORCE_CONSTEXPR20
string to_string(
const T& value) {
101 if (value.begin() == value.end()) {
105 for (
auto iter = value.begin(); iter != value.end(); ++iter) {
106 if (iter != value.begin()) {
121template <
typename T, enable_if_t<is_unbounded_array_v<T>,
int> = 0>
122NEFORCE_NODISCARD NEFORCE_CONSTEXPR20
string to_string(
const T&) {
132template <
typename T, enable_if_t<is_bounded_array_v<T> && !is_c
string_v<T>,
int> = 0>
133NEFORCE_NODISCARD NEFORCE_CONSTEXPR20
string to_string(
const T& arr) {
134 return inner::collector_to_string(arr);
144template <
typename IfEmpty,
typename T>
156template <
typename IfEmpty,
typename T>
168template <
typename T1,
typename T2>
176template <
typename Tuple,
size_t I, enable_if_t<I == tuple_size_v<Tuple> - 1,
int> = 0>
177NEFORCE_CONSTEXPR20
void __to_string_tuple_elements(
const Tuple& t,
string& result) {
181template <
typename Tuple,
size_t I,
183 const Tuple& t,
string& result) {
185 inner::__to_string_tuple_elements<Tuple, I + 1>(t, result);
188template <
typename... UArgs,
enable_if_t<
sizeof...(UArgs) == 0,
int> = 0>
189NEFORCE_CONSTEXPR20
string __to_string_tuple_dispatch(
const tuple<UArgs...>&) {
193template <
typename... UArgs,
enable_if_t<
sizeof...(UArgs) != 0,
int> = 0>
194NEFORCE_CONSTEXPR20
string __to_string_tuple_dispatch(
const tuple<UArgs...>& t) {
197 inner::__to_string_tuple_elements<decltype(t), 0>(t, result);
211template <
typename... Args>
212NEFORCE_NODISCARD NEFORCE_CONSTEXPR20
string to_string(
const tuple<Args...>& tup) {
213 return inner::__to_string_tuple_dispatch(tup);
217#ifndef NEFORCE_STANDARD_17
221string to_string_concat(T&& t) {
224template <
typename First,
typename... Rest>
225string to_string_concat(First&& first, Rest&&... rest) {
238template <
typename... Args,
enable_if_t<(
sizeof...(Args) > 1),
int> = 0>
239NEFORCE_NODISCARD NEFORCE_CONSTEXPR20
string to_string(Args&&... args) {
240#ifdef NEFORCE_STANDARD_17
243 return inner::to_string_concat(_NEFORCE
forward<Args>(args)...);
250#ifdef NEFORCE_ARCH_BITS_32
252template <
typename CharT,
typename UT>
253constexpr enable_if_t<(
sizeof(UT) > 4)> __uint_to_buff_aux(CharT* riter, UT& ux)
noexcept {
254 while (ux >
static_cast<UT
>(0xFFFFFFFFU)) {
255 auto chunk =
static_cast<uint32_t>(ux %
static_cast<UT
>(1000000000));
256 ux /=
static_cast<UT
>(1000000000);
257 for (
int idx = 0; idx != 9; ++idx) {
258 *--riter =
static_cast<CharT
>(
'0' + chunk % 10);
264template <
typename CharT,
typename UT>
265constexpr enable_if_t<(
sizeof(UT) <= 4)> __uint_to_buff_aux(CharT*, UT&)
noexcept {}
277template <
typename CharT,
typename UT>
278NEFORCE_NODISCARD
constexpr CharT* __uint_to_buff(CharT* riter, UT ux)
noexcept {
281#ifdef NEFORCE_ARCH_BITS_64
284 inner::__uint_to_buff_aux(riter, ux);
285 auto holder =
static_cast<uint32_t>(ux);
288 *--riter =
static_cast<CharT
>(
'0' + holder %
static_cast<UT
>(10));
289 holder /=
static_cast<UT
>(10);
290 }
while (
static_cast<UT
>(holder) !=
static_cast<UT
>(0));
301template <
typename CharT,
typename T>
306 CharT*
const buffer_end = buffer + 21;
307 CharT* rnext = buffer_end;
309 const auto unsigned_x =
static_cast<UT
>(x);
311 rnext = inner::__uint_to_buff(rnext,
static_cast<UT
>(0 - unsigned_x));
314 rnext = inner::__uint_to_buff(rnext, unsigned_x);
316 const size_t count = buffer_end - rnext;
327template <
typename CharT,
typename T>
332 constexpr size_t buffer_size =
extent_v<
decltype(buffer)>;
333 CharT*
const buffer_end = buffer + buffer_size;
334 CharT*
const rnext = inner::__uint_to_buff(buffer_end, x);
335 const size_t count = buffer_end - rnext;
346NEFORCE_CONSTEXPR20
string __uint_to_string_base(
uint64_t value,
const int base,
const bool uppercase) {
354 constexpr auto digits_lower =
"0123456789abcdef";
355 constexpr auto digits_upper =
"0123456789ABCDEF";
356 const auto digits = uppercase ? digits_upper : digits_lower;
368template <
typename T, enable_if_t<disjunction_v<conjunction<is_standard_
integral<T>, is_
signed<T>>>,
int> = 0>
369NEFORCE_NODISCARD NEFORCE_CONSTEXPR20
string __int_to_string_dispatch(
const T x) {
370 return inner::__int_to_string<char>(x);
372template <
typename T, enable_if_t<disjunction_v<conjunction<is_standard_
integral<T>, is_
unsigned<T>>>,
int> = 0>
373NEFORCE_NODISCARD NEFORCE_CONSTEXPR20
string __int_to_string_dispatch(
const T x) {
374 return inner::__uint_to_string<char>(x);
387template <
typename CharT,
typename T>
389__float_to_string_with_precision(T x,
int precision = 6,
const bool force_scientific =
false,
390 const bool force_fixed =
false) {
417 bool use_scientific =
false;
420 if (force_scientific) {
421 use_scientific =
true;
422 }
else if (force_fixed) {
423 use_scientific =
false;
425 use_scientific = (x != 0) && (x >= 1e6 || x < 1e-4);
428 if (use_scientific && x != 0) {
429 const double log_val =
logarithm_10(
static_cast<double>(x));
430 exponent =
static_cast<int>(log_val >= 0 ? log_val : log_val - 1.0);
433 for (
int i = 0; i < exponent; ++i) {
434 x /=
static_cast<T
>(10);
437 for (
int i = 0; i < -exponent; ++i) {
438 x *=
static_cast<T
>(10);
442 if (x >=
static_cast<T
>(10)) {
443 x /=
static_cast<T
>(10);
445 }
else if (x <
static_cast<T
>(1) && x >
static_cast<T
>(0)) {
446 x *=
static_cast<T
>(10);
451 auto integer_part =
static_cast<uint64_t>(x);
452 T fractional_part = x -
static_cast<T
>(integer_part);
458 const int safe_precision = (precision > 18) ? 18 : precision;
459 for (
int i = 0; i < safe_precision; ++i) {
463 frac_int =
static_cast<uint64_t>(fractional_part *
static_cast<T
>(frac_scale) +
static_cast<T
>(0.5));
465 if (frac_int >= frac_scale) {
466 frac_int -= frac_scale;
469 if (use_scientific && integer_part >= 10) {
476 result += inner::__uint_to_string<CharT>(integer_part);
479 result +=
static_cast<CharT
>(
'.');
482 const int safe_precision = (precision > 18) ? 18 : precision;
483 const int leading_zeros = safe_precision -
static_cast<int>(frac_str.
size());
484 for (
int i = 0; i < leading_zeros; ++i) {
485 result +=
static_cast<CharT
>(
'0');
489 for (
int i = safe_precision; i < precision; ++i) {
490 result +=
static_cast<CharT
>(
'0');
494 if (use_scientific) {
495 result +=
static_cast<CharT
>(
'e');
497 result +=
static_cast<CharT
>(
'+');
499 result +=
static_cast<CharT
>(
'-');
500 exponent = -exponent;
503 result +=
static_cast<CharT
>(
'0');
505 result += inner::__uint_to_string<CharT>(
static_cast<uint64_t>(exponent));
518template <typename CharT, typename T, enable_if_t<is_floating_point<T>::value,
int> = 0>
520 return inner::__float_to_string_with_precision<CharT>(x, 6,
false,
false);
534template <typename T, enable_if_t<is_floating_point<T>::value,
int> = 0>
536 return inner::__float_to_string_with_precision<char>(x, precision, scientific, !scientific);
546template <typename T, enable_if_t<is_floating_point<T>::value,
int> = 0>
548 return inner::__float_to_string_with_precision<char>(x, precision,
false,
false);
558template <typename T, enable_if_t<is_floating_point<T>::value,
int> = 0>
560 return inner::__float_to_string_with_precision<char>(x, precision,
false,
true);
570template <typename T, enable_if_t<is_floating_point<T>::value,
int> = 0>
572 return inner::__float_to_string_with_precision<char>(x, precision,
true,
false);
577NEFORCE_END_NAMESPACE__
NEFORCE_CONSTEXPR20 void reserve(const size_type n)
预留容量
NEFORCE_NODISCARD NEFORCE_CONSTEXPR20 size_type size() const noexcept
获取字符数
NEFORCE_CONSTEXPR20 void push_back(value_type value)
在末尾插入字符
NEFORCE_CONSTEXPR20 void reverse() noexcept
反转字符串
static NEFORCE_NODISCARD constexpr T infinity() noexcept
获取正无穷大表示
NEFORCE_NODISCARD constexpr T && forward(remove_reference_t< T > &x) noexcept
完美转发左值
NEFORCE_INLINE17 constexpr size_t extent_v
extent的便捷变量模板
NEFORCE_ALWAYS_INLINE enable_if_t< is_void_v< T >, future_result_t< T > > get(future< T > &f)
通用future结果获取函数
NEFORCE_INLINE17 constexpr bool is_floating_point_v
is_floating_point的便捷变量模板
NEFORCE_INLINE17 constexpr bool is_integral_v
is_integral的便捷变量模板
typename package< T >::type package_t
package的便捷别名
NEFORCE_INLINE17 constexpr bool is_unsigned_v
is_unsigned的便捷变量模板
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)
统计范围内等于指定值的元素数量
NEFORCE_PURE_FUNCTION NEFORCE_CONSTEXPR14 decimal_t logarithm_10(const decimal_t x)
计算以10为底的对数
NEFORCE_CONST_FUNCTION NEFORCE_CONSTEXPR14 decimal_t remainder(const decimal_t x, const decimal_t y) noexcept
计算余数
NEFORCE_CONST_FUNCTION constexpr bool is_nan(const T x) noexcept
检查浮点数是否为NaN
NEFORCE_CONST_FUNCTION constexpr bool is_negative(const T x) noexcept
检查浮点数是否为负数
typename make_unsigned< T >::type make_unsigned_t
make_unsigned的便捷别名
NEFORCE_NODISCARD NEFORCE_CONSTEXPR20 string to_string_with_precision(T x, int precision, bool scientific=false)
将浮点数转换为字符串(带精度控制)
NEFORCE_NODISCARD NEFORCE_CONSTEXPR20 string to_string_fixed(T x, int precision=6)
将浮点数转换为字符串(固定小数格式)
NEFORCE_NODISCARD NEFORCE_CONSTEXPR20 string to_string(const T &value)
将可包装类型转换为字符串
NEFORCE_NODISCARD NEFORCE_CONSTEXPR20 string to_string_scientific(T x, int precision=6)
将浮点数转换为字符串(科学计数法格式)
NEFORCE_NODISCARD NEFORCE_CONSTEXPR20 string to_string_general(T x, int precision=6)
将浮点数转换为字符串(通用格式)
NEFORCE_NODISCARD NEFORCE_CONSTEXPR20 string address_string(const void *p)
将指针转换为十六进制地址字符串
NEFORCE_NODISCARD NEFORCE_ALWAYS_INLINE constexpr decltype(auto) begin(Container &cont) noexcept(noexcept(cont.begin()))
获取容器的起始迭代器
NEFORCE_NODISCARD NEFORCE_ALWAYS_INLINE constexpr bool empty(const Container &cont) noexcept(noexcept(cont.empty()))
检查容器是否为空
NEFORCE_NODISCARD NEFORCE_ALWAYS_INLINE constexpr decltype(auto) cbegin(const Container &cont) noexcept(noexcept(cont.cbegin()))
获取const容器的const起始迭代器
NEFORCE_NODISCARD NEFORCE_ALWAYS_INLINE constexpr decltype(auto) cend(const Container &cont) noexcept(noexcept(cont.cend()))
获取const容器的const结束迭代器
typename enable_if< Test, T >::type enable_if_t
enable_if的便捷别名