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);
98#ifdef NEFORCE_STANDARD_20
99template <
typename T, enable_if_t<is_base_of_v<ranges::view_base<T>, T>,
int> = 0>
100NEFORCE_NODISCARD NEFORCE_CONSTEXPR20
string to_string(
const T& value) {
102 if (value.begin() == value.end()) {
106 for (
auto iter = value.begin(); iter != value.end(); ++iter) {
107 if (iter != value.begin()) {
123template <
typename T, enable_if_t<is_unbounded_array_v<T>,
int> = 0>
124NEFORCE_NODISCARD NEFORCE_CONSTEXPR20
string to_string(
const T& ) {
134template <
typename T, enable_if_t<is_bounded_array_v<T> && !is_c
string_v<T>,
int> = 0>
135NEFORCE_NODISCARD NEFORCE_CONSTEXPR20
string to_string(
const T& arr) {
136 return inner::collector_to_string(arr);
146template <
typename IfEmpty,
typename T>
158template <
typename IfEmpty,
typename T>
170template <
typename T1,
typename T2>
178template <
typename Tuple,
size_t I, enable_if_t<I == tuple_size_v<Tuple> - 1,
int> = 0>
179NEFORCE_CONSTEXPR20
void __to_string_tuple_elements(
const Tuple& t,
string& result) {
183template <
typename Tuple,
size_t I,
185 const Tuple& t,
string& result) {
187 inner::__to_string_tuple_elements<Tuple, I + 1>(t, result);
190template <
typename... UArgs,
enable_if_t<
sizeof...(UArgs) == 0,
int> = 0>
191NEFORCE_CONSTEXPR20
string __to_string_tuple_dispatch(
const tuple<UArgs...>& ) {
195template <
typename... UArgs,
enable_if_t<
sizeof...(UArgs) != 0,
int> = 0>
196NEFORCE_CONSTEXPR20
string __to_string_tuple_dispatch(
const tuple<UArgs...>& t) {
199 inner::__to_string_tuple_elements<decltype(t), 0>(t, result);
213template <
typename... Args>
214NEFORCE_NODISCARD NEFORCE_CONSTEXPR20
string to_string(
const tuple<Args...>& tup) {
215 return inner::__to_string_tuple_dispatch(tup);
219#ifndef NEFORCE_STANDARD_17
223string to_string_concat(T&& t) {
226template <
typename First,
typename... Rest>
227string to_string_concat(First&& first, Rest&&... rest) {
240template <
typename... Args,
enable_if_t<(
sizeof...(Args) > 1),
int> = 0>
241NEFORCE_NODISCARD NEFORCE_CONSTEXPR20
string to_string(Args&&... args) {
242#ifdef NEFORCE_STANDARD_17
245 return inner::to_string_concat(_NEFORCE
forward<Args>(args)...);
252#ifdef NEFORCE_ARCH_BITS_32
254template <
typename CharT,
typename UT>
255constexpr enable_if_t<(
sizeof(UT) > 4)> __uint_to_buff_aux(CharT*& riter, UT& ux) {
256 while (ux >
static_cast<UT
>(0xFFFFFFFFU)) {
257 auto chunk =
static_cast<uint32_t>(ux %
static_cast<UT
>(1000000000));
258 ux /=
static_cast<UT
>(1000000000);
259 for (
int idx = 0; idx != 9; ++idx) {
260 *--riter =
static_cast<CharT
>(
'0' + chunk % 10);
266template <
typename CharT,
typename UT>
267constexpr enable_if_t<(
sizeof(UT) <= 4)> __uint_to_buff_aux(CharT*, UT&)
noexcept {}
279template <
typename CharT,
typename UT>
280NEFORCE_NODISCARD
constexpr CharT* __uint_to_buff(CharT* riter, UT ux) {
283#ifdef NEFORCE_ARCH_BITS_64
286 *--riter =
static_cast<CharT
>(
static_cast<UT
>(
'0') + holder %
static_cast<UT
>(10));
287 holder /=
static_cast<UT
>(10);
288 }
while (holder !=
static_cast<UT
>(0));
290 inner::__uint_to_buff_aux(riter, ux);
291 auto holder =
static_cast<uint32_t>(ux);
293 *--riter =
static_cast<CharT
>(
'0' + holder % 10);
295 }
while (holder != 0);
307template <
typename CharT,
typename T>
312 CharT*
const buffer_end = buffer + 40;
313 CharT* rnext = buffer_end;
315 const auto unsigned_x =
static_cast<UT
>(x);
317 rnext = inner::__uint_to_buff(rnext,
static_cast<UT
>(
static_cast<UT
>(0) - unsigned_x));
320 rnext = inner::__uint_to_buff(rnext, unsigned_x);
322 const size_t count = buffer_end - rnext;
333template <
typename CharT,
typename T>
338 CharT*
const buffer_end = buffer + 40;
339 CharT*
const rnext = inner::__uint_to_buff(buffer_end, x);
340 const size_t count = buffer_end - rnext;
344template <
typename T, enable_if_t<is_
signed_v<T>,
int> = 0>
345NEFORCE_NODISCARD NEFORCE_CONSTEXPR20
string __int_to_string_dispatch(T x) {
346 return inner::__int_to_string<char>(x);
348template <
typename T, enable_if_t<is_
unsigned_v<T>,
int> = 0>
349NEFORCE_NODISCARD NEFORCE_CONSTEXPR20
string __int_to_string_dispatch(T x) {
350 return inner::__uint_to_string<char>(x);
363template <
typename CharT,
typename T>
365__float_to_string_with_precision(T x,
int precision = 6,
const bool force_scientific =
false,
366 const bool force_fixed =
false) {
389 precision = _NEFORCE
max(precision, 0);
391 bool use_scientific =
false;
394 if (force_scientific) {
395 use_scientific =
true;
396 }
else if (force_fixed) {
397 use_scientific =
false;
399 use_scientific = (x != 0) && (x >= 1e6 || x < 1e-4);
402 if (use_scientific && x != 0) {
403 const double log_val =
logarithm_10(
static_cast<double>(x));
404 exponent =
static_cast<int>(log_val >= 0 ? log_val : log_val - 1.0);
407 for (
int i = 0; i < exponent; ++i) {
408 x /=
static_cast<T
>(10);
411 for (
int i = 0; i < -exponent; ++i) {
412 x *=
static_cast<T
>(10);
416 if (x >=
static_cast<T
>(10)) {
417 x /=
static_cast<T
>(10);
419 }
else if (x <
static_cast<T
>(1) && x >
static_cast<T
>(0)) {
420 x *=
static_cast<T
>(10);
425 auto integer_part =
static_cast<uint64_t>(x);
426 T fractional_part = x -
static_cast<T
>(integer_part);
432 const int safe_precision = (precision > 18) ? 18 : precision;
433 for (
int i = 0; i < safe_precision; ++i) {
437 frac_int =
static_cast<uint64_t>(fractional_part *
static_cast<T
>(frac_scale) +
static_cast<T
>(0.5));
439 if (frac_int >= frac_scale) {
440 frac_int -= frac_scale;
443 if (use_scientific && integer_part >= 10) {
450 result += inner::__uint_to_string<CharT>(integer_part);
453 result +=
static_cast<CharT
>(
'.');
456 const int safe_precision = (precision > 18) ? 18 : precision;
457 const int leading_zeros = safe_precision -
static_cast<int>(frac_str.
size());
458 for (
int i = 0; i < leading_zeros; ++i) {
459 result +=
static_cast<CharT
>(
'0');
463 for (
int i = safe_precision; i < precision; ++i) {
464 result +=
static_cast<CharT
>(
'0');
468 if (use_scientific) {
469 result +=
static_cast<CharT
>(
'e');
471 result +=
static_cast<CharT
>(
'+');
473 result +=
static_cast<CharT
>(
'-');
474 exponent = -exponent;
477 result +=
static_cast<CharT
>(
'0');
479 result += inner::__uint_to_string<CharT>(
static_cast<uint64_t>(exponent));
492template <typename CharT, typename T, enable_if_t<is_floating_point<T>::value,
int> = 0>
494 return inner::__float_to_string_with_precision<CharT>(x, 6,
false,
false);
508template <typename T, enable_if_t<is_floating_point<T>::value,
int> = 0>
510 return inner::__float_to_string_with_precision<char>(x, precision, scientific, !scientific);
520template <typename T, enable_if_t<is_floating_point<T>::value,
int> = 0>
522 return inner::__float_to_string_with_precision<char>(x, precision,
false,
false);
532template <typename T, enable_if_t<is_floating_point<T>::value,
int> = 0>
534 return inner::__float_to_string_with_precision<char>(x, precision,
false,
true);
544template <typename T, enable_if_t<is_floating_point<T>::value,
int> = 0>
546 return inner::__float_to_string_with_precision<char>(x, precision,
true,
false);
551NEFORCE_END_NAMESPACE__
constexpr size_type size() const noexcept
获取字符数
static constexpr T infinity() noexcept
获取正无穷大表示
constexpr T && forward(remove_reference_t< T > &x) noexcept
完美转发左值
enable_if_t< is_void_v< T >, future_result_t< T > > get(future< T > &f)
通用future结果获取函数
constexpr bool is_integral_v
is_integral的便捷变量模板
constexpr bool is_floating_point_v
is_floating_point的便捷变量模板
constexpr bool is_unsigned_v
is_unsigned的便捷变量模板
typename package< T >::type package_t
package的便捷别名
constexpr const T & max(const T &a, const T &b, Compare comp) noexcept(noexcept(comp(a, b)))
返回两个值中的较大者
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)
统计范围内等于指定值的元素数量
constexpr decimal_t logarithm_10(const decimal_t x)
计算以10为底的对数
constexpr bool is_nan(const T x) noexcept
检查浮点数是否为NaN
constexpr bool is_negative(const T x) noexcept
检查浮点数是否为负数
typename make_unsigned< T >::type make_unsigned_t
make_unsigned的便捷别名
constexpr string to_string_with_precision(T x, int precision, bool scientific=false)
将浮点数转换为字符串(带精度控制)
constexpr string to_string_general(T x, int precision=6)
将浮点数转换为字符串(通用格式)
constexpr string to_string_scientific(T x, int precision=6)
将浮点数转换为字符串(科学计数法格式)
constexpr string to_string_fixed(T x, int precision=6)
将浮点数转换为字符串(固定小数格式)
constexpr string to_string(const T &value)
将可包装类型转换为字符串
constexpr string address_string(const void *p)
将指针转换为十六进制地址字符串
constexpr decltype(auto) begin(Container &cont) noexcept(noexcept(cont.begin()))
获取容器的起始迭代器
constexpr bool empty(const Container &cont) noexcept(noexcept(cont.empty()))
检查容器是否为空
constexpr decltype(auto) cbegin(const Container &cont) noexcept(noexcept(cont.cbegin()))
获取const容器的const起始迭代器
constexpr decltype(auto) cend(const Container &cont) noexcept(noexcept(cont.cend()))
获取const容器的const结束迭代器
typename enable_if< Test, T >::type enable_if_t
enable_if的便捷别名