The YSLib project - main repository
Revisión | 74e1025f0a02da2590b2578c8adad8008f60d581 (tree) |
---|---|
Tiempo | 2024-04-19 23:42:25 |
Autor | FrankHB <frankhb1989@gmai...> |
Commiter | FrankHB |
更新主分支版本: build 983 rev 10 。
@@ -17,6 +17,7 @@ | ||
17 | 17 | <ClInclude Include="include\libdefect\cmath.h" /> |
18 | 18 | <ClInclude Include="include\libdefect\cstdio.h" /> |
19 | 19 | <ClInclude Include="include\libdefect\exception.h" /> |
20 | + <ClInclude Include="include\libdefect\limits.hpp" /> | |
20 | 21 | <ClInclude Include="include\libdefect\string.h" /> |
21 | 22 | <ClInclude Include="include\stdinc.h" /> |
22 | 23 | <ClInclude Include="include\ydef.h" /> |
@@ -26,6 +27,7 @@ | ||
26 | 27 | <ClInclude Include="include\ystdex\any.h" /> |
27 | 28 | <ClInclude Include="include\ystdex\any_iterator.hpp" /> |
28 | 29 | <ClInclude Include="include\ystdex\apply.hpp" /> |
30 | + <ClInclude Include="include\ystdex\arithmetic.hpp" /> | |
29 | 31 | <ClInclude Include="include\ystdex\array.hpp" /> |
30 | 32 | <ClInclude Include="include\ystdex\base.h" /> |
31 | 33 | <ClInclude Include="include\ystdex\bind.hpp" /> |
@@ -35,6 +37,8 @@ | ||
35 | 37 | <ClInclude Include="include\ystdex\cassert.h" /> |
36 | 38 | <ClInclude Include="include\ystdex\cast.hpp" /> |
37 | 39 | <ClInclude Include="include\ystdex\cctype.h" /> |
40 | + <ClInclude Include="include\ystdex\charconv.h" /> | |
41 | + <ClInclude Include="include\ystdex\chrono.hpp" /> | |
38 | 42 | <ClInclude Include="include\ystdex\compose.hpp" /> |
39 | 43 | <ClInclude Include="include\ystdex\compressed_pair.hpp" /> |
40 | 44 | <ClInclude Include="include\ystdex\concurrency.h" /> |
@@ -68,6 +72,7 @@ | ||
68 | 72 | <ClInclude Include="include\ystdex\iterator.hpp" /> |
69 | 73 | <ClInclude Include="include\ystdex\iterator_op.hpp" /> |
70 | 74 | <ClInclude Include="include\ystdex\iterator_trait.hpp" /> |
75 | + <ClInclude Include="include\ystdex\limits.hpp" /> | |
71 | 76 | <ClInclude Include="include\ystdex\list.hpp" /> |
72 | 77 | <ClInclude Include="include\ystdex\map.hpp" /> |
73 | 78 | <ClInclude Include="include\ystdex\memory.hpp" /> |
@@ -320,6 +320,21 @@ | ||
320 | 320 | <ClInclude Include="include\ystdex\flat_set.hpp"> |
321 | 321 | <Filter>include\ystdex</Filter> |
322 | 322 | </ClInclude> |
323 | + <ClInclude Include="include\ystdex\chrono.hpp"> | |
324 | + <Filter>include\ystdex</Filter> | |
325 | + </ClInclude> | |
326 | + <ClInclude Include="include\libdefect\limits.hpp"> | |
327 | + <Filter>include\libdefect</Filter> | |
328 | + </ClInclude> | |
329 | + <ClInclude Include="include\ystdex\limits.hpp"> | |
330 | + <Filter>include\ystdex</Filter> | |
331 | + </ClInclude> | |
332 | + <ClInclude Include="include\ystdex\arithmetic.hpp"> | |
333 | + <Filter>include\ystdex</Filter> | |
334 | + </ClInclude> | |
335 | + <ClInclude Include="include\ystdex\charconv.h"> | |
336 | + <Filter>include\ystdex</Filter> | |
337 | + </ClInclude> | |
323 | 338 | </ItemGroup> |
324 | 339 | <ItemGroup> |
325 | 340 | <ClCompile Include="source\ystdex\cstdio.cpp"> |
@@ -0,0 +1,236 @@ | ||
1 | +/* | |
2 | + © 2024 FrankHB. | |
3 | + | |
4 | + This file is part of the YSLib project, and may only be used, modified, | |
5 | + and distributed under the terms of the YSLib project license. | |
6 | + By continuing to use, modify, or distribute this file you indicate that | |
7 | + you have read the license and understand and accept it fully. | |
8 | +*/ | |
9 | + | |
10 | +/*! \file limits.hpp | |
11 | +\ingroup LibDefect | |
12 | +\brief 标准库实现 \c \<limits> 修正。 | |
13 | +\version r235 | |
14 | +\author FrankHB <frankhb1989@gmail.com> | |
15 | +\since build 983 | |
16 | +\par 创建时间: | |
17 | + 2024-04-06 13:26:40 +0800 | |
18 | +\par 修改时间: | |
19 | + 2024-04-06 15:05 +0800 | |
20 | +\par 文本编码: | |
21 | + UTF-8 | |
22 | +\par 模块名称: | |
23 | + LibDefect::Limits | |
24 | +*/ | |
25 | + | |
26 | + | |
27 | +#ifndef YB_INC_libdefect_limits_hpp_ | |
28 | +#define YB_INC_libdefect_limits_hpp_ 1 | |
29 | + | |
30 | +#include <limits> | |
31 | + | |
32 | +// See See https://gcc.gnu.org/bugzilla/show_bug.cgi?id=96042. | |
33 | +// NOTE: Fixed @ 10.3. | |
34 | + | |
35 | +// NOTE: See https://gcc.gnu.org/onlinedocs/libstdc++/manual/using_macros.html. | |
36 | +#if defined __GLIBCXX__ && (__GLIBCXX__ < 20200819 || _GLIBCXX_RELEASE < 10) | |
37 | + | |
38 | +namespace std _GLIBCXX_VISIBILITY(default) | |
39 | +{ | |
40 | + | |
41 | +#if defined __STRICT_ANSI__ && defined __SIZEOF_INT128__ | |
42 | +__extension__ | |
43 | +template<> | |
44 | +struct numeric_limits<__int128> | |
45 | +{ | |
46 | + static _GLIBCXX_USE_CONSTEXPR bool is_specialized = true; | |
47 | + | |
48 | + static _GLIBCXX_CONSTEXPR __int128 | |
49 | + min() _GLIBCXX_USE_NOEXCEPT | |
50 | + { | |
51 | + // XXX: Assume this uses a 2's complement representation. | |
52 | + return -((__int128(1) << 126) - 1 << 1) - 2; | |
53 | + } | |
54 | + | |
55 | + static _GLIBCXX_CONSTEXPR __int128 | |
56 | + max() _GLIBCXX_USE_NOEXCEPT | |
57 | + { | |
58 | + return ((__int128(1) << 126) - 1 << 1) + 1; | |
59 | + } | |
60 | + | |
61 | +#if __cplusplus >= 201103L | |
62 | + static constexpr __int128 | |
63 | + lowest() noexcept | |
64 | + { | |
65 | + return min(); | |
66 | + } | |
67 | +#endif | |
68 | + | |
69 | + static _GLIBCXX_USE_CONSTEXPR int digits = 127; | |
70 | + static _GLIBCXX_USE_CONSTEXPR int digits10 = 127 * 643L / 2136; | |
71 | +#if __cplusplus >= 201103L | |
72 | + static constexpr int max_digits10 = 0; | |
73 | +#endif | |
74 | + static _GLIBCXX_USE_CONSTEXPR bool is_signed = true; | |
75 | + static _GLIBCXX_USE_CONSTEXPR bool is_integer = true; | |
76 | + static _GLIBCXX_USE_CONSTEXPR bool is_exact = true; | |
77 | + static _GLIBCXX_USE_CONSTEXPR int radix = 2; | |
78 | + | |
79 | + static _GLIBCXX_CONSTEXPR __int128 | |
80 | + epsilon() _GLIBCXX_USE_NOEXCEPT | |
81 | + { | |
82 | + return 0; | |
83 | + } | |
84 | + | |
85 | + static _GLIBCXX_CONSTEXPR __int128 | |
86 | + round_error() _GLIBCXX_USE_NOEXCEPT | |
87 | + { | |
88 | + return 0; | |
89 | + } | |
90 | + | |
91 | + static _GLIBCXX_USE_CONSTEXPR int min_exponent = 0; | |
92 | + static _GLIBCXX_USE_CONSTEXPR int min_exponent10 = 0; | |
93 | + static _GLIBCXX_USE_CONSTEXPR int max_exponent = 0; | |
94 | + static _GLIBCXX_USE_CONSTEXPR int max_exponent10 = 0; | |
95 | + | |
96 | + static _GLIBCXX_USE_CONSTEXPR bool has_infinity = false; | |
97 | + static _GLIBCXX_USE_CONSTEXPR bool has_quiet_NaN = false; | |
98 | + static _GLIBCXX_USE_CONSTEXPR bool has_signaling_NaN = false; | |
99 | + static _GLIBCXX_USE_CONSTEXPR float_denorm_style has_denorm = denorm_absent; | |
100 | + static _GLIBCXX_USE_CONSTEXPR bool has_denorm_loss = false; | |
101 | + | |
102 | + static _GLIBCXX_CONSTEXPR __int128 | |
103 | + infinity() _GLIBCXX_USE_NOEXCEPT | |
104 | + { | |
105 | + return static_cast<__int128>(0); | |
106 | + } | |
107 | + | |
108 | + static _GLIBCXX_CONSTEXPR __int128 | |
109 | + quiet_NaN() _GLIBCXX_USE_NOEXCEPT | |
110 | + { | |
111 | + return static_cast<__int128>(0); | |
112 | + } | |
113 | + | |
114 | + static _GLIBCXX_CONSTEXPR __int128 | |
115 | + signaling_NaN() _GLIBCXX_USE_NOEXCEPT | |
116 | + { | |
117 | + return static_cast<__int128>(0); | |
118 | + } | |
119 | + | |
120 | + static _GLIBCXX_CONSTEXPR __int128 | |
121 | + denorm_min() _GLIBCXX_USE_NOEXCEPT | |
122 | + { | |
123 | + return static_cast<__int128>(0); | |
124 | + } | |
125 | + | |
126 | + static _GLIBCXX_USE_CONSTEXPR bool is_iec559 = false; | |
127 | + static _GLIBCXX_USE_CONSTEXPR bool is_bounded = true; | |
128 | + static _GLIBCXX_USE_CONSTEXPR bool is_modulo = false; | |
129 | + | |
130 | + static _GLIBCXX_USE_CONSTEXPR bool traps = __glibcxx_integral_traps; | |
131 | + static _GLIBCXX_USE_CONSTEXPR bool tinyness_before = false; | |
132 | + static _GLIBCXX_USE_CONSTEXPR float_round_style round_style | |
133 | + = round_toward_zero; | |
134 | +}; | |
135 | + | |
136 | +__extension__ | |
137 | +template<> | |
138 | +struct numeric_limits<unsigned __int128> | |
139 | +{ | |
140 | + static _GLIBCXX_USE_CONSTEXPR bool is_specialized = true; | |
141 | + | |
142 | + static _GLIBCXX_CONSTEXPR unsigned __int128 | |
143 | + min() _GLIBCXX_USE_NOEXCEPT | |
144 | + { | |
145 | + return 0; | |
146 | + } | |
147 | + | |
148 | + static _GLIBCXX_CONSTEXPR unsigned __int128 | |
149 | + max() _GLIBCXX_USE_NOEXCEPT | |
150 | + { | |
151 | + return ~static_cast<unsigned __int128>(0); | |
152 | + } | |
153 | + | |
154 | +#if __cplusplus >= 201103L | |
155 | + static constexpr unsigned __int128 | |
156 | + lowest() noexcept | |
157 | + { | |
158 | + return min(); | |
159 | + } | |
160 | + | |
161 | +#endif | |
162 | + static _GLIBCXX_USE_CONSTEXPR int digits = 128; | |
163 | + static _GLIBCXX_USE_CONSTEXPR int digits10 = 128 * 643L / 2136; | |
164 | +#if __cplusplus >= 201103L | |
165 | + static constexpr int max_digits10 = 0; | |
166 | +#endif | |
167 | + static _GLIBCXX_USE_CONSTEXPR bool is_signed = false; | |
168 | + static _GLIBCXX_USE_CONSTEXPR bool is_integer = true; | |
169 | + static _GLIBCXX_USE_CONSTEXPR bool is_exact = true; | |
170 | + static _GLIBCXX_USE_CONSTEXPR int radix = 2; | |
171 | + | |
172 | + static _GLIBCXX_CONSTEXPR unsigned __int128 | |
173 | + epsilon() _GLIBCXX_USE_NOEXCEPT | |
174 | + { | |
175 | + return 0; | |
176 | + } | |
177 | + | |
178 | + static _GLIBCXX_CONSTEXPR unsigned __int128 | |
179 | + round_error() _GLIBCXX_USE_NOEXCEPT | |
180 | + { | |
181 | + return 0; | |
182 | + } | |
183 | + | |
184 | + static _GLIBCXX_USE_CONSTEXPR int min_exponent = 0; | |
185 | + static _GLIBCXX_USE_CONSTEXPR int min_exponent10 = 0; | |
186 | + static _GLIBCXX_USE_CONSTEXPR int max_exponent = 0; | |
187 | + static _GLIBCXX_USE_CONSTEXPR int max_exponent10 = 0; | |
188 | + | |
189 | + static _GLIBCXX_USE_CONSTEXPR bool has_infinity = false; | |
190 | + static _GLIBCXX_USE_CONSTEXPR bool has_quiet_NaN = false; | |
191 | + static _GLIBCXX_USE_CONSTEXPR bool has_signaling_NaN = false; | |
192 | + static _GLIBCXX_USE_CONSTEXPR float_denorm_style has_denorm | |
193 | + = denorm_absent; | |
194 | + static _GLIBCXX_USE_CONSTEXPR bool has_denorm_loss = false; | |
195 | + | |
196 | + static _GLIBCXX_CONSTEXPR unsigned __int128 | |
197 | + infinity() _GLIBCXX_USE_NOEXCEPT | |
198 | + { | |
199 | + return static_cast<unsigned __int128>(0); | |
200 | + } | |
201 | + | |
202 | + static _GLIBCXX_CONSTEXPR unsigned __int128 | |
203 | + quiet_NaN() _GLIBCXX_USE_NOEXCEPT | |
204 | + { | |
205 | + return static_cast<unsigned __int128>(0); | |
206 | + } | |
207 | + | |
208 | + static _GLIBCXX_CONSTEXPR unsigned __int128 | |
209 | + signaling_NaN() _GLIBCXX_USE_NOEXCEPT | |
210 | + { | |
211 | + return static_cast<unsigned __int128>(0); | |
212 | + } | |
213 | + | |
214 | + static _GLIBCXX_CONSTEXPR unsigned __int128 | |
215 | + denorm_min() _GLIBCXX_USE_NOEXCEPT | |
216 | + { | |
217 | + return static_cast<unsigned __int128>(0); | |
218 | + } | |
219 | + | |
220 | + static _GLIBCXX_USE_CONSTEXPR bool is_iec559 = false; | |
221 | + static _GLIBCXX_USE_CONSTEXPR bool is_bounded = true; | |
222 | + static _GLIBCXX_USE_CONSTEXPR bool is_modulo = true; | |
223 | + | |
224 | + static _GLIBCXX_USE_CONSTEXPR bool traps = __glibcxx_integral_traps; | |
225 | + static _GLIBCXX_USE_CONSTEXPR bool tinyness_before = false; | |
226 | + static _GLIBCXX_USE_CONSTEXPR float_round_style round_style | |
227 | + = round_toward_zero; | |
228 | +}; | |
229 | +#endif | |
230 | + | |
231 | +} // namespace std; | |
232 | + | |
233 | +#endif | |
234 | + | |
235 | +#endif | |
236 | + |
@@ -1,5 +1,5 @@ | ||
1 | 1 | /* |
2 | - © 2009-2023 FrankHB. | |
2 | + © 2009-2024 FrankHB. | |
3 | 3 | |
4 | 4 | This file is part of the YSLib project, and may only be used, modified, |
5 | 5 | and distributed under the terms of the YSLib project license. |
@@ -18,13 +18,13 @@ | ||
18 | 18 | /*! \file ydef.h |
19 | 19 | \ingroup YBase |
20 | 20 | \brief 语言实现和系统环境相关特性及公用类型和宏的基础定义。 |
21 | -\version r4589 | |
21 | +\version r4704 | |
22 | 22 | \author FrankHB <frankhb1989@gmail.com> |
23 | 23 | \since 早于 build 132 |
24 | 24 | \par 创建时间: |
25 | 25 | 2009-12-02 21:42:44 +0800 |
26 | 26 | \par 修改时间: |
27 | - 2023-05-27 20:26 +0800 | |
27 | + 2024-04-05 23:51 +0800 | |
28 | 28 | \par 文本编码: |
29 | 29 | UTF-8 |
30 | 30 | \par 模块名称: |
@@ -152,6 +152,14 @@ | ||
152 | 152 | # define _SILENCE_CXX23_ALIGNED_UNION_DEPRECATION_WARNING |
153 | 153 | # endif |
154 | 154 | #endif |
155 | + | |
156 | +#if YB_IMPL_MSCPP >= 1937 | |
157 | +// NOTE: See https://github.com/microsoft/STL/commit/522149cff1132b1bf70bee38ca5edbe4d7ce11a5. | |
158 | +//! \since bulid 980 | |
159 | +# ifndef _SILENCE_CXX23_DENORM_DEPRECATION_WARNING | |
160 | +# define _SILENCE_CXX23_DENORM_DEPRECATION_WARNING | |
161 | +# endif | |
162 | +#endif | |
155 | 163 | //!@} |
156 | 164 | |
157 | 165 | /*! |
@@ -161,7 +169,7 @@ | ||
161 | 169 | //!@{ |
162 | 170 | /*! |
163 | 171 | \note 检测的属性不是标准属性。 |
164 | -\see http://clang.llvm.org/docs/LanguageExtensions.html#has-attribute 。 | |
172 | +\see https://clang.llvm.org/docs/LanguageExtensions.html#has-attribute 。 | |
165 | 173 | \see https://github.com/cplusplus/nbballot/issues/128 。 |
166 | 174 | \since build 628 |
167 | 175 | */ |
@@ -170,7 +178,7 @@ | ||
170 | 178 | #endif |
171 | 179 | |
172 | 180 | /*! |
173 | -\see http://clang.llvm.org/docs/LanguageExtensions.html#has-builtin 。 | |
181 | +\see https://clang.llvm.org/docs/LanguageExtensions.html#has-builtin 。 | |
174 | 182 | \see https://gcc.gnu.org/bugzilla/show_bug.cgi?id=66970 。 |
175 | 183 | \since build 535 |
176 | 184 | */ |
@@ -179,7 +187,15 @@ | ||
179 | 187 | #endif |
180 | 188 | |
181 | 189 | /*! |
182 | -\see http://clang.llvm.org/docs/LanguageExtensions.html#has-cpp-attribute 。 | |
190 | +\see https://clang.llvm.org/docs/LanguageExtensions.html#feature-checking-macros 。 | |
191 | +\since build 983 | |
192 | +*/ | |
193 | +#ifndef __has_constepxr_builtin | |
194 | +# define __has_constepxr_builtin(...) 0 | |
195 | +#endif | |
196 | + | |
197 | +/*! | |
198 | +\see https://clang.llvm.org/docs/LanguageExtensions.html#has-cpp-attribute 。 | |
183 | 199 | \see https://releases.llvm.org/10.0.0/tools/clang/docs/LanguageExtensions.html 。 |
184 | 200 | \since build 591 |
185 | 201 | */ |
@@ -187,7 +203,10 @@ | ||
187 | 203 | # define __has_cpp_attribute(...) 0 |
188 | 204 | #endif |
189 | 205 | |
190 | -//! \see http://clang.llvm.org/docs/LanguageExtensions.html#has-feature-and-has-extension 。 | |
206 | +/*! | |
207 | +\see https://clang.llvm.org/docs/LanguageExtensions.html#has-feature-and-has-extension 。 | |
208 | +\see https://github.com/llvm/llvm-project/blob/main/clang/include/clang/Basic/Features.def 。 | |
209 | +*/ | |
191 | 210 | //!@{ |
192 | 211 | #ifndef __has_extension |
193 | 212 | # define __has_extension(...) __has_feature(__VA_ARGS__) |
@@ -199,7 +218,7 @@ | ||
199 | 218 | //!@} |
200 | 219 | |
201 | 220 | /*! |
202 | -\see http://clang.llvm.org/docs/LanguageExtensions.html#has-include 。 | |
221 | +\see https://clang.llvm.org/docs/LanguageExtensions.html#has-include 。 | |
203 | 222 | \since build 831 |
204 | 223 | */ |
205 | 224 | #ifndef __has_include |
@@ -340,7 +359,7 @@ | ||
340 | 359 | /*! |
341 | 360 | \brief 带宏替换的记号连接。 |
342 | 361 | \see WG21 N4140 16.3.3[cpp.concat]/3 。 |
343 | -\see http://gcc.gnu.org/onlinedocs/cpp/Concatenation.html 。 | |
362 | +\see https://gcc.gnu.org/onlinedocs/cpp/Concatenation.html 。 | |
344 | 363 | \see https://www.securecoding.cert.org/confluence/display/cplusplus/PRE05-CPP.+Understand+macro+replacement+when+concatenating+tokens+or+performing+stringification 。 |
345 | 364 | |
346 | 365 | 注意 ISO C++ 未确定宏定义内 # 和 ## 操作符求值顺序。 |
@@ -441,7 +460,7 @@ | ||
441 | 460 | /*! \defgroup lang_impl_features Language Implementation Features |
442 | 461 | \brief 语言实现的特性。 |
443 | 462 | \see https://blogs.msdn.microsoft.com/vcblog/2015/06/19/c111417-features-in-vs-2015-rtm/ 。 |
444 | -\see http://clang.llvm.org/docs/LanguageExtensions.html 。 | |
463 | +\see https://clang.llvm.org/docs/LanguageExtensions.html 。 | |
445 | 464 | \since build 294 |
446 | 465 | */ |
447 | 466 | //!@{ |
@@ -506,6 +525,34 @@ | ||
506 | 525 | |
507 | 526 | |
508 | 527 | /*! |
528 | +\def YB_HAS_int128 | |
529 | +\brief 128 位整数类型支持。 | |
530 | +\note 对 GCC 和 Clang 可能需使用 \c __extension__ 在严格标准模式下避免警告。 | |
531 | +\see https://gcc.gnu.org/onlinedocs/gcc-4.6.0/gcc/C-Extensions.html#C-Extensions 。 | |
532 | +\see https://docs.nvidia.com/cuda/cuda-compiler-driver-nvcc/index.html 。 | |
533 | +\since build 983 | |
534 | +*/ | |
535 | +#undef YB_HAS_int128 | |
536 | +// NOTE: This is available since GCC 4.6 for specific targets. | |
537 | +// XXX: Since the support is specific to targets, the detection via additional | |
538 | +// macro %__SIZEOF_INT128__ is needed. However, it is still not precise, e.g. | |
539 | +// Clang++ may support 128-bit integer types (since 3.1) without such macro | |
540 | +// definition (before 3.3). Just not bother on architecture other than x86_64 | |
541 | +// as now. See also https://stackoverflow.com/a/54815033 for more details | |
542 | +// about detecting the support. However, it may even broken on some other | |
543 | +// platforms not formally supported by this project, e.g. NVCC does not support | |
544 | +// it even when the macro is defined (see | |
545 | +// https://svn.boost.org/trac10/ticket/10418). | |
546 | +// TODO: Support %__INTEL_COMPILER? | |
547 | +#if (YB_IMPL_CLANGPP >= 30100 && defined __x86_64__) \ | |
548 | + || (__SIZEOF_INT128__ == 16 && YB_IMPL_GNUC && !defined __CUDACC__) | |
549 | +# define YB_HAS_int128 true | |
550 | +#else | |
551 | +# define YB_HAS_int128 false | |
552 | +#endif | |
553 | + | |
554 | + | |
555 | +/*! | |
509 | 556 | \def YB_ABORT |
510 | 557 | \brief 非正常终止程序。 |
511 | 558 | \note 可能使用体系结构相关实现或标准库 std::abort 函数等。 |
@@ -823,9 +870,9 @@ | ||
823 | 870 | \brief 修饰类定义要求实现不生成初始化动态类型信息。 |
824 | 871 | \note 只适用于定义不在初始化派生类对象时的动态类型的类,否则行为未定义。 |
825 | 872 | \see https://docs.microsoft.com/cpp/cpp/novtable 。 |
826 | -\see http://releases.llvm.org/3.7.0/tools/clang/docs/AttributeReference.html 。 | |
873 | +\see https://releases.llvm.org/3.7.0/tools/clang/docs/AttributeReference.html 。 | |
827 | 874 | \see https://clang.llvm.org/docs/AttributeReference.html#novtable 。 |
828 | -\see http://lists.llvm.org/pipermail/cfe-commits/Week-of-Mon-20150720/133747.html 。 | |
875 | +\see https://lists.llvm.org/pipermail/cfe-commits/Week-of-Mon-20150720/133747.html 。 | |
829 | 876 | \since build 842 |
830 | 877 | \todo 确认可忽略不支持情形的 Clang++ 最近可用的版本。 |
831 | 878 |
@@ -854,8 +901,8 @@ | ||
854 | 901 | \brief 指示返回非空属性。 |
855 | 902 | \since build 676 |
856 | 903 | \see https://clang.llvm.org/docs/AttributeReference.html#returns-nonnull 。 |
857 | -\see http://reviews.llvm.org/rL199626 。 | |
858 | -\see http://reviews.llvm.org/rL199790 。 | |
904 | +\see https://reviews.llvm.org/rL199626 。 | |
905 | +\see https://reviews.llvm.org/rL199790 。 | |
859 | 906 | \todo 确认 Clang++ 最低可用的版本。 |
860 | 907 | */ |
861 | 908 | #if __has_attribute(__returns_nonnull__) || YB_IMPL_GNUCPP >= 40900 \ |
@@ -1158,6 +1205,56 @@ | ||
1158 | 1205 | #endif |
1159 | 1206 | //!@} |
1160 | 1207 | |
1208 | +/*! | |
1209 | +\def YB_Use_int128 | |
1210 | +\brief 使用 128 位(有符号和无符号)整数类型。 | |
1211 | +\since build 983 | |
1212 | + | |
1213 | +检查 \c std::uintmax_t 的值并确定 128 位整数支持。替换的值有: | |
1214 | + \li \c 4 :\c std::uintmax_t 大于 128 位无符号整数的最大值。 | |
1215 | + \li \c 3 :\c std::uintmax_t 等于 128 位无符号整数的最大值。 | |
1216 | + \li \c 2 :\c std::uintmax_t 大于 64 位但小于 128 位的无符号整数的最大值。 | |
1217 | + \li \c 1 :\c std::uintmax_t 等于 64 位无符号整数的最大值。 | |
1218 | + \li \c 0 :不存在 128 位整数支持。 | |
1219 | +*/ | |
1220 | +// NOTE: A conforming implementation uses %std::uintmax_t for all unsigned | |
1221 | +// arithmetic types here. Extended integer-like types may be excluded from | |
1222 | +// integer types (e.g. in libstdc++ with strict standard modes). | |
1223 | +#ifndef YB_Use_int128 | |
1224 | +# if YB_HAS_int128 | |
1225 | +// XXX: Bit width shall not greater than the width of %std::uintmax_t, otherwise | |
1226 | +// the behavior is undefined. 64 is safe because it is the least bets of | |
1227 | +// 'unsigned long long' which is in turn not greater than %std::uintmax_t in | |
1228 | +// bit width for the value representation. | |
1229 | +# if ~0U >> 63 >> 63 >> 2!= 0 | |
1230 | +# define YB_Use_int128 4 | |
1231 | +# elif ((~0U >> 1) + 1) >> 63 >> 1 == 1U << 63 | |
1232 | +# define YB_Use_int128 3 | |
1233 | +# elif (~0U >> 1) + 1 > 1U << 63 | |
1234 | +# define YB_Use_int128 2 | |
1235 | +# elif (~0U >> 1) + 1 == 1U << 63 | |
1236 | +# define YB_Use_int128 1 | |
1237 | +# else | |
1238 | +// NOTE: The type %std::uintmax_t shall be at least as the greatest standard | |
1239 | +// unsigned integer type, i.e. 'unsigned long long', which is at least 64-bit. | |
1240 | +# error "Nonconforming implementation found." | |
1241 | +# endif | |
1242 | +# else | |
1243 | +# define YB_Use_int128 0 | |
1244 | +# endif | |
1245 | +#endif | |
1246 | + | |
1247 | +/*! | |
1248 | +\def YB_MaxIntBits | |
1249 | +\brief YBase 实现支持的最大整数位宽。 | |
1250 | +*/ | |
1251 | + | |
1252 | +#if YB_Use_int128 > 0 | |
1253 | +# define YB_MaxIntBits 128U | |
1254 | +#else | |
1255 | +# define YB_MaxIntBits 64U | |
1256 | +#endif | |
1257 | + | |
1161 | 1258 | |
1162 | 1259 | /*! \defgroup YBase_pseudo_keyword YBase Specified Pseudo-Keywords |
1163 | 1260 | \brief YBase 指定的替代关键字。 |
@@ -1554,6 +1651,22 @@ | ||
1554 | 1651 | */ |
1555 | 1652 | #define yunseq ystdex::unsequenced |
1556 | 1653 | |
1654 | + | |
1655 | +/*! | |
1656 | +\brief 128 位整数类型。 | |
1657 | +\note 可避免直接使用内建支持的类型时需要 \c __extension__ 。 | |
1658 | +\since build 983 | |
1659 | +*/ | |
1660 | +//!@{ | |
1661 | +#if YB_Use_int128 > 0 | |
1662 | +__extension__ using int128_t = __int128; | |
1663 | +__extension__ using uint128_t = unsigned __int128; | |
1664 | +# define YB_MaxIntBits 128U | |
1665 | +#else | |
1666 | +# define YB_MaxIntBits 64U | |
1667 | +#endif | |
1668 | +//!@} | |
1669 | + | |
1557 | 1670 | } // namespace ystdex; |
1558 | 1671 | |
1559 | 1672 | #endif |
@@ -1,23 +1,22 @@ | ||
1 | 1 | /* |
2 | 2 | © 2014-2023 FrankHB. |
3 | 3 | |
4 | - This file is part of the YSLib project, and may only be used, | |
5 | - modified, and distributed under the terms of the YSLib project | |
6 | - license, LICENSE.TXT. By continuing to use, modify, or distribute | |
7 | - this file you indicate that you have read the license and | |
8 | - understand and accept it fully. | |
4 | + This file is part of the YSLib project, and may only be used, modified, | |
5 | + and distributed under the terms of the YSLib project license. | |
6 | + By continuing to use, modify, or distribute this file you indicate that | |
7 | + you have read the license and understand and accept it fully. | |
9 | 8 | */ |
10 | 9 | |
11 | 10 | /*! \file allocator.hpp |
12 | 11 | \ingroup YStandardEx |
13 | 12 | \brief 分配器接口。 |
14 | -\version r6303 | |
13 | +\version r6319 | |
15 | 14 | \author FrankHB <frankhb1989@gmail.com> |
16 | 15 | \since build 882 |
17 | 16 | \par 创建时间: |
18 | 17 | 2020-02-10 21:34:28 +0800 |
19 | 18 | \par 修改时间: |
20 | - 2023-04-11 03:40 +0800 | |
19 | + 2023-04-16 20:10 +0800 | |
21 | 20 | \par 文本编码: |
22 | 21 | UTF-8 |
23 | 22 | \par 模块名称: |
@@ -79,13 +78,15 @@ | ||
79 | 78 | #endif |
80 | 79 | |
81 | 80 | |
82 | -#if __cplusplus >= 202002L && (!defined(__GLIBCXX__) || __GLIBCXX__ > 20190731) | |
83 | -// XXX: See https://github.com/cplusplus/draft/issues/3111. | |
84 | -// XXX: See https://gcc.gnu.org/git/?p=gcc.git;a=blobdiff;f=libstdc%2B%2B-v3/include/std/memory;h=0a483d2d8d1a1287685cb5cc8a7d338a14e7fef3;hp=3036802f8c3eb1c3013dc1720ad85087e5202694;hb=3090082cbefd8b1374f237bd4242b554490b2933;hpb=e6c847fb8f90b1c119a677b81cfc294b13eb7772. | |
81 | +// NOTE: See https://github.com/cplusplus/draft/issues/3111. | |
82 | +// NOTE: See https://gcc.gnu.org/git/?p=gcc.git;a=blobdiff;f=libstdc%2B%2B-v3/include/std/memory;h=0a483d2d8d1a1287685cb5cc8a7d338a14e7fef3;hp=3036802f8c3eb1c3013dc1720ad85087e5202694;hb=3090082cbefd8b1374f237bd4242b554490b2933;hpb=e6c847fb8f90b1c119a677b81cfc294b13eb7772. | |
85 | 83 | // XXX: The source of libstdc++ uses '__cpp_lib_make_obj_using_allocator' |
86 | 84 | // internally in headers like <memory_resource> and <scoped_allocator> to |
87 | 85 | // detect the existence of the features. This is not in ISO C++ or proposals |
88 | 86 | // and not used here. |
87 | +// NOTE: See https://reviews.llvm.org/D131898. | |
88 | +#if __cplusplus >= 202002L && (!defined __GLIBCXX__ || __GLIBCXX__ > 20190731) \ | |
89 | + && (!defined _LIBCPP_VERSION || _LIBCPP_VERSION > 160000) | |
89 | 90 | //! \since build 863 |
90 | 91 | //!@{ |
91 | 92 | using std::uses_allocator_construction_args; |
@@ -290,7 +291,7 @@ | ||
290 | 291 | }; |
291 | 292 | |
292 | 293 | // XXX: This is a workaround to implementation without support of WG21 N4387. |
293 | -# if (defined(__GLIBCXX__) && (__GLIBCXX__ <= 20150630 \ | |
294 | +# if (defined __GLIBCXX__ && (__GLIBCXX__ <= 20150630 \ | |
294 | 295 | || YB_IMPL_GNUCPP < 60000)) && !(_LIBCPP_VERSION > 4000 \ |
295 | 296 | || __cplusplus >= 201703L) |
296 | 297 | // NOTE: See https://gcc.gnu.org/git/?p=gcc.git;a=blobdiff;f=libstdc%2B%2B-v3/include/bits/stl_pair.h;h=6672ecb227377d199df830bc475f6ebecd03beed;hp=490b00565a0560f9f15f86bb706fa8f3800ee026;hb=bf7818bfb0c70e626f8b71501ada3263f306a476;hpb=ddb63209a8dc059a7b2a137d7a1859222bb43dd6, |
@@ -910,7 +911,7 @@ | ||
910 | 911 | operator=(const allocator_guard_delete& d) ynothrow |
911 | 912 | { |
912 | 913 | ystdex::copy_assign(get_allocator(), d.first()); |
913 | - return *this; | |
914 | + return *this; | |
914 | 915 | } |
915 | 916 | // XXX: No 'ynothrow' is specified because the underlying assignment |
916 | 917 | // operator might be deleted. |
@@ -1047,7 +1048,7 @@ | ||
1047 | 1048 | operator=(const allocator_delete& d) ynothrow |
1048 | 1049 | { |
1049 | 1050 | ystdex::copy_assign(get_allocator(), d.get()); |
1050 | - return *this; | |
1051 | + return *this; | |
1051 | 1052 | } |
1052 | 1053 | allocator_delete& |
1053 | 1054 | operator=(allocator_delete&&) = default; |
@@ -1321,8 +1322,7 @@ | ||
1321 | 1322 | //! \since build 941 |
1322 | 1323 | //!@{ |
1323 | 1324 | /*! |
1324 | -\ingroup customization_points | |
1325 | -\ingroup traits | |
1325 | +\ingroup customization_points traits | |
1326 | 1326 | \note 可定制和分配器的定义中不同的操作。 |
1327 | 1327 | */ |
1328 | 1328 | //! \brief 分配器在容器中的使用复制构造的传播特征。 |
@@ -0,0 +1,840 @@ | ||
1 | +/* | |
2 | + © 2024 FrankHB. | |
3 | + | |
4 | + This file is part of the YSLib project, and may only be used, modified, | |
5 | + and distributed under the terms of the YSLib project license. | |
6 | + By continuing to use, modify, or distribute this file you indicate that | |
7 | + you have read the license and understand and accept it fully. | |
8 | +*/ | |
9 | + | |
10 | +/*! \file arithmetic.hpp | |
11 | +\ingroup YStandardEx | |
12 | +\brief 算术类型和操作。 | |
13 | +\version r839 | |
14 | +\author FrankHB <frankhb1989@gmail.com> | |
15 | +\since build 983 | |
16 | +\par 创建时间: | |
17 | + 2024-04-08 04:41:56 +0800 | |
18 | +\par 修改时间: | |
19 | + 2024-04-18 22:10 +0800 | |
20 | +\par 文本编码: | |
21 | + UTF-8 | |
22 | +\par 模块名称: | |
23 | + YStandardEx::Arithmetic | |
24 | +*/ | |
25 | + | |
26 | + | |
27 | +#ifndef YB_INC_ystdex_arithmetic_hpp_ | |
28 | +#define YB_INC_ystdex_arithmetic_hpp_ 1 | |
29 | + | |
30 | +#include "cstdint.hpp" // for "cstdint.hpp", enable_if_t, integer_width, | |
31 | +// make_width_int, is_same, is_integral, std::intmax_t, identity, | |
32 | +// std::uintmax_t, _t, cond_t, is_signed, make_signed, remove_cv_t, | |
33 | +// is_unsigned, std::numeric_limits (with fixes), bool_, __has_builtin, | |
34 | +// is_unbounded_number; | |
35 | +#include <cmath> // for <cmath>, std::float_t; | |
36 | +#include "exception.h" // for "exception.h", throw_overflow_error, | |
37 | +// throw_underflow_error; | |
38 | +#include "allocator.hpp" // for ystdex::make_obj_using_allocator; | |
39 | + | |
40 | +namespace ystdex | |
41 | +{ | |
42 | + | |
43 | +//! \brief 正整数幂。 | |
44 | +template<typename _type, typename _type2> | |
45 | +YB_ATTR_nodiscard YB_STATELESS yconstfn | |
46 | + yimpl(enable_if_unsigned_t)<_type2, _type> | |
47 | +upow(_type x, _type2 e) ynothrow | |
48 | +{ | |
49 | + return e == 0 ? _type(1) : e == 1 | |
50 | + ? x : ystdex::upow(x * x, e >> 1) * ((e & 1) != 0 ? x : _type(1)); | |
51 | +} | |
52 | + | |
53 | + | |
54 | +//! \since build 983 | |
55 | +//!@{ | |
56 | +namespace details | |
57 | +{ | |
58 | + | |
59 | +template<typename _type, typename = void> | |
60 | +struct extend_int_map; | |
61 | + | |
62 | +// XXX: This is needed to non-standard types with width not greater than 64, | |
63 | +// e.g. %__int64 in Microsoft VC++. For width greater than 64, it also seems | |
64 | +// more consistent to have this way (to be filter by %integer_width and | |
65 | +// %make_width_int). | |
66 | +template<typename _type> | |
67 | +struct extend_int_map<_type, enable_if_t<(integer_width<_type>() | |
68 | + <= YB_MaxIntBits)>> : make_width_int<integer_width<_type>{}> | |
69 | +{ | |
70 | + static_assert(!is_same<bool, _type>(), "Boolean types found."); | |
71 | + static_assert(is_integral<_type>(), "Unsupported type found."); | |
72 | +}; | |
73 | + | |
74 | + | |
75 | +template<typename> | |
76 | +struct ext_add_overflow; | |
77 | + | |
78 | +// NOTE: This is only enabled when %std::intmax_t is greater than 'long long', | |
79 | +// to prevent violation of ODR. | |
80 | +#if ULLONG_MAX < ~0U | |
81 | +// NOTE: Prefer %intmax_t if greater than %std::intmax_t. | |
82 | +template<> | |
83 | +struct ext_add_overflow<std::intmax_t> | |
84 | + : yimpl(conditional)<(integer_width<std::intmax_t>() < integer_width< | |
85 | + intmax_t>()), identity<intmax_t>, ext_add_overflow<std::uintmax_t>> | |
86 | +{}; | |
87 | +#endif | |
88 | + | |
89 | +// NOTE: It is guarnteed that %intmax_t is not less than %std::intmax_t. Prefer | |
90 | +// %std::intmax_t if greater than 'long long'; otherwise prefer %intmax_t. | |
91 | +template<> | |
92 | +struct ext_add_overflow<long long> : yimpl(conditional)<( | |
93 | + integer_width<long long>() < integer_width<std::intmax_t>()), std::intmax_t, | |
94 | + conditional_t<(integer_width<long long>() < integer_width<intmax_t>()), | |
95 | + intmax_t, unsigned long long>> | |
96 | +{}; | |
97 | + | |
98 | +template<> | |
99 | +struct ext_add_overflow<long> | |
100 | + : yimpl(conditional)<(integer_width<long>() < integer_width<long long>()), | |
101 | + long long, _t<ext_add_overflow<long long>>> | |
102 | +{}; | |
103 | + | |
104 | +template<> | |
105 | +struct ext_add_overflow<unsigned long long> : yimpl(identity)<std::float_t> | |
106 | +{}; | |
107 | + | |
108 | +template<> | |
109 | +struct ext_add_overflow<int> | |
110 | + : yimpl(conditional_t)<(integer_width<int>() < integer_width<long>()), | |
111 | + identity<long>, ext_add_overflow<long>> | |
112 | +{}; | |
113 | + | |
114 | +template<> | |
115 | +struct ext_add_overflow<short> | |
116 | + : yimpl(conditional_t)<(integer_width<short>() < integer_width<int>()), | |
117 | + identity<int>, ext_add_overflow<int>> | |
118 | +{}; | |
119 | + | |
120 | +template<> | |
121 | +struct ext_add_overflow<signed char> : yimpl(identity)<short> | |
122 | +{}; | |
123 | + | |
124 | +// XXX: For non standard integer types not having same width of standard ones, | |
125 | +// results are unspecified. | |
126 | +template<typename _type> | |
127 | +struct ext_add_overflow | |
128 | + : ext_add_overflow<_t<details::extend_int_map<_type>>> | |
129 | +{}; | |
130 | + | |
131 | + | |
132 | +// NOTE: Unsigned underflow only happens in cases where an unsigned value is | |
133 | +// subtracted by a value with lower rank, so there is no extension of the bit | |
134 | +// width. | |
135 | +template<typename _type> | |
136 | +struct ext_add_underflow | |
137 | + : cond_t<is_signed<_type>, ext_add_overflow<_type>, make_signed<_type>> | |
138 | +{}; | |
139 | +// XXX: Given that the unsigned integer types all have the exact same width as | |
140 | +// their signed counterpart, there is no need to add specialization to test the | |
141 | +// sizes here, except that for cases of 'unsigned long long' result which shall | |
142 | +// be alterted to 'std::float_t' (which has been also handled in the primary | |
143 | +// template in this implementation). | |
144 | + | |
145 | +} // namespace details; | |
146 | + | |
147 | +/*! | |
148 | +\ingroup transformation_traits | |
149 | +\pre 静态断言:参数是整数。 | |
150 | +*/ | |
151 | +//!@{ | |
152 | +/*! | |
153 | +\brief 扩展能避免算术上溢的整数加法结果类型。 | |
154 | + | |
155 | +取避免计算整数类型的和或差时的上溢的结果类型,可包括以下情形: | |
156 | + 对两个相同的整数类型,两个正整数值相加。 | |
157 | + 对两个相同的有符号整数类型,非负整数值减有符号整数的最小值。 | |
158 | + 对两个相同的有符号整数类型,正整数值减负整数值。 | |
159 | +结果升阶作为两个相同整数类型的加法结果的整数: | |
160 | + 若参数是 cv 限定的类型,则结果同无 cv 限定的类型添加相同的 cv 限定。 | |
161 | + 否则,若参数是最大的无符号整数类型,结果是 \c std::float_t 。 | |
162 | + 否则,若没有对应参数更大的有符号整数类型,则结果为对应的无符号整数类型。 | |
163 | + 否则,结果是具有最小的更大的算术转换阶的有符号整数类型。 | |
164 | +结果选取支持的类型中能保证可表示计算结果中阶最小的。 | |
165 | +因此,除最大的无符号整数类型,其它结果是有符号类型。 | |
166 | +*/ | |
167 | +//!@{ | |
168 | +template<typename _type> | |
169 | +struct extend_additive_overflow | |
170 | + : copy_cv<_t<details::ext_add_overflow<remove_cv_t<_type>>>, _type> | |
171 | +{}; | |
172 | + | |
173 | +template<typename _type> | |
174 | +using extend_additive_overflow_t = _t<extend_additive_overflow<_type>>; | |
175 | +//!@} | |
176 | + | |
177 | + | |
178 | +/*! | |
179 | +\brief 扩展能避免算术下溢的整数加减法结果类型。 | |
180 | +\sa extend_additive_overflow | |
181 | + | |
182 | +取避免计算整数类型的和或差时的下溢的结果类型,可包括以下情形: | |
183 | + 对两个相同的有符号整数类型,两个负整数值相加。 | |
184 | + 对两个相同的有符号整数类型,负整数值相加。 | |
185 | + 对两个相同的有符号整数类型,负整数值减正整数值。 | |
186 | + 对整数类型,整数值减一个任意的更小的转换阶的正整数值。 | |
187 | +结果升阶作为两个相同整数类型的加法或减法结果的整数: | |
188 | + 若参数是 cv 限定的类型,则结果同无 cv 限定的类型添加相同的 cv 限定。 | |
189 | + 否则,若 extend_additive_overflow 对相同参数类型的结果是有符号数, | |
190 | + 则同 extend_additive_overflow 。 | |
191 | + 否则,若参数是最大的有符号或无符号整数类型,结果是 \c std::float_t 。 | |
192 | + 否则,若参数是有符号类型,结果同 extend_additive_overflow 。 | |
193 | + 否则,参数是对应的有符号类型。 | |
194 | +结果选取支持的类型中能保证可表示计算结果。因此,结果总是有符号类型。 | |
195 | +无符号数参数不扩展位宽,因为转换阶较小。这可支持自减等操作。 | |
196 | +若需要支持转换阶更大的减数,结果即减数的类型。这不需要基于被减数的类型扩展位宽。 | |
197 | +*/ | |
198 | +//!@{ | |
199 | +template<typename _type> | |
200 | +struct extend_additive_underflow | |
201 | + : copy_cv<_t<details::ext_add_underflow<remove_cv_t<_type>>>, _type> | |
202 | +{}; | |
203 | + | |
204 | +template<typename _type> | |
205 | +using extend_additive_underflow_t = _t<extend_additive_underflow<_type>>; | |
206 | +//!@} | |
207 | + | |
208 | + | |
209 | +/*! | |
210 | +\brief 扩展能避免算术溢出的整数乘法结果类型。 | |
211 | + | |
212 | +取避免计算整数类型的积时的溢出的结果类型,可包括以下情形: | |
213 | + 两个相同的有符号整数类型相乘。 | |
214 | + 两个相同的无符号整数类型相乘。 | |
215 | +结果升阶作为两个相同整数类型的加法或减法结果的整数: | |
216 | + 若参数是 cv 限定的类型,则结果同无 cv 限定的类型添加相同的 cv 限定。 | |
217 | + 否则,若参数是最大的有符号或无符号整数类型,结果是 \c std::float_t 。 | |
218 | + 否则,结果同 make_widen_int 。 | |
219 | +结果总是 \c std::float_t 或与参数类型相同符号的整数类型。 | |
220 | +*/ | |
221 | +//!@{ | |
222 | +template<typename _type> | |
223 | +struct extend_product : conditional_t<integer_width<_type>() == YB_MaxIntBits, | |
224 | + identity<std::float_t>, make_widen_int<_type>> | |
225 | +{ | |
226 | + static_assert(!is_same<bool, _type>(), "Boolean types found."); | |
227 | + static_assert(is_integral<_type>(), "Unsupported type found."); | |
228 | +}; | |
229 | + | |
230 | +template<typename _type> | |
231 | +using extend_product_t = _t<extend_product<_type>>; | |
232 | +//!@} | |
233 | +//!@} | |
234 | + | |
235 | + | |
236 | +namespace details | |
237 | +{ | |
238 | + | |
239 | +template<typename _tTo, typename _tFrom, bool = is_unsigned<_tTo>{}> | |
240 | +struct int_min_check final | |
241 | +{ | |
242 | + static void | |
243 | + check_underflow(const _tFrom& x) | |
244 | + { | |
245 | + if(YB_UNLIKELY(x < std::numeric_limits<_tTo>::min())) | |
246 | + throw_underflow_error("Value underflow detected in cast."); | |
247 | + } | |
248 | +}; | |
249 | + | |
250 | +template<typename _tTo, typename _tFrom> | |
251 | +struct int_min_check<_tTo, _tFrom, true> final | |
252 | +{ | |
253 | + static void | |
254 | + check_overflow(const _tFrom& x) | |
255 | + { | |
256 | + if(YB_UNLIKELY(x < _tFrom(0))) | |
257 | + throw_overflow_error(); | |
258 | + } | |
259 | +}; | |
260 | + | |
261 | + | |
262 | +template<typename _tTo, typename _tFrom> | |
263 | +struct int_max_check final | |
264 | +{ | |
265 | + static void | |
266 | + check_overflow(const _tFrom& x) | |
267 | + { | |
268 | + if(YB_UNLIKELY(x > std::numeric_limits<_tTo>::max())) | |
269 | + throw_overflow_error(); | |
270 | + } | |
271 | +}; | |
272 | + | |
273 | + | |
274 | +//! \ingroup functors | |
275 | +//!@{ | |
276 | +template<typename _tTo, typename _tFrom, bool, bool> | |
277 | +struct checked_conv_int | |
278 | +{ | |
279 | + YB_ATTR_nodiscard YB_PURE _tTo | |
280 | + operator()(const _tFrom& x) const | |
281 | + { | |
282 | + int_max_check<_tTo, _tFrom>::check_overflow(x); | |
283 | + int_min_check<_tTo, _tFrom>::check_underflow(x); | |
284 | + return static_cast<_tTo>(x); | |
285 | + } | |
286 | +}; | |
287 | + | |
288 | +template<typename _tTo, typename _tFrom> | |
289 | +struct checked_conv_int<_tTo, _tFrom, true, false> | |
290 | +{ | |
291 | + YB_ATTR_nodiscard YB_PURE _tTo | |
292 | + operator()(const _tFrom& x) const | |
293 | + { | |
294 | + int_max_check<_tTo, _tFrom>::check_overflow(x); | |
295 | + return static_cast<_tTo>(x); | |
296 | + } | |
297 | +}; | |
298 | + | |
299 | +template<typename _tTo, typename _tFrom> | |
300 | +struct checked_conv_int<_tTo, _tFrom, false, true> | |
301 | +{ | |
302 | + YB_ATTR_nodiscard YB_PURE _tTo | |
303 | + operator()(const _tFrom& x) const | |
304 | + { | |
305 | + int_min_check<_tTo, _tFrom>::check_underflow(x); | |
306 | + return static_cast<_tTo>(x); | |
307 | + } | |
308 | +}; | |
309 | + | |
310 | +template<typename _tTo, typename _tFrom> | |
311 | +struct checked_conv_int<_tTo, _tFrom, false, false> | |
312 | +{ | |
313 | + YB_ATTR_nodiscard YB_PURE _tTo | |
314 | + operator()(const _tFrom& x) const ynothrow | |
315 | + { | |
316 | + return static_cast<_tTo>(x); | |
317 | + } | |
318 | +}; | |
319 | +//!@} | |
320 | + | |
321 | + | |
322 | +//! \ingroup traits | |
323 | +//!@{ | |
324 | +template<typename _type, bool = std::numeric_limits<_type>::is_signed, | |
325 | + bool = __has_builtin(__builtin_add_overflow) && is_integral<_type>{}> | |
326 | +struct ext_plus; | |
327 | + | |
328 | +template<typename _type> | |
329 | +struct ext_plus<_type, false, false> | |
330 | +{ | |
331 | + template<typename _tRes, typename _tExt, typename = _tExt> | |
332 | + YB_ATTR_nodiscard YB_PURE static inline _tRes | |
333 | + extended_plus(const _type& x, const _type& y) | |
334 | + { | |
335 | + // NOTE: Wrapped integers are generally more efficient. | |
336 | +#if true | |
337 | + const _type r(x + y); | |
338 | + | |
339 | + return r >= x ? _tRes(r) : _tRes(_tExt(x) + _tExt(y)); | |
340 | +#else | |
341 | + return y <= numeric_limits<_type>::max() - x ? _tRes(x + y) | |
342 | + : _tRes(_tExt(x) + _tExt(y)); | |
343 | +#endif | |
344 | + } | |
345 | + template<typename _tRes, typename _tExt, typename = _tExt, class _tAlloc> | |
346 | + YB_ATTR_nodiscard YB_PURE static inline _tRes | |
347 | + extended_plus(const _type& x, const _type& y, const _tAlloc& a) | |
348 | + { | |
349 | +#if true | |
350 | + const _type r(x + y); | |
351 | + | |
352 | + return r >= x ? ystdex::make_obj_using_allocator<_tRes>(a, r) | |
353 | + : ystdex::make_obj_using_allocator<_tRes>(a, _tExt(x) + _tExt(y)); | |
354 | +#else | |
355 | + return y <= numeric_limits<_type>::max() - x | |
356 | + ? ystdex::make_obj_using_allocator<_tRes>(a, x + y) | |
357 | + : ystdex::make_obj_using_allocator<_tRes>(a, _tExt(x) + _tExt(y)); | |
358 | +#endif | |
359 | + } | |
360 | +}; | |
361 | + | |
362 | +template<typename _type> | |
363 | +struct ext_plus<_type, true, false> | |
364 | +{ | |
365 | + using limits_t = std::numeric_limits<_type>; | |
366 | + | |
367 | + template<typename _tRes, typename _tExt, typename _tExt2> | |
368 | + YB_ATTR_nodiscard YB_PURE static inline _tRes | |
369 | + extended_plus(const _type& x, const _type& y) | |
370 | + { | |
371 | + if(x > 0 && y > limits_t::max() - x) | |
372 | + return _tRes(_tExt(x) + _tExt(y)); | |
373 | + if(x < 0 && y < limits_t::min() - x) | |
374 | + return _tRes(_tExt2(x) + _tExt2(y)); | |
375 | + return _tRes(x + y); | |
376 | + } | |
377 | + template<typename _tRes, typename _tExt, typename _tExt2, class _tAlloc> | |
378 | + YB_ATTR_nodiscard YB_PURE static inline _tRes | |
379 | + extended_plus(const _type& x, const _type& y, const _tAlloc& a) | |
380 | + { | |
381 | + if(x > 0 && y > limits_t::max() - x) | |
382 | + return | |
383 | + ystdex::make_obj_using_allocator<_tRes>(a, _tExt(x) + _tExt(y)); | |
384 | + if(x < 0 && y < limits_t::min() - x) | |
385 | + return ystdex::make_obj_using_allocator<_tRes>(a, | |
386 | + _tExt2(x) + _tExt2(y)); | |
387 | + return ystdex::make_obj_using_allocator<_tRes>(a, x + y); | |
388 | + } | |
389 | +}; | |
390 | + | |
391 | +#if __has_builtin(__builtin_add_overflow) | |
392 | +template<typename _type> | |
393 | +struct ext_plus<_type, false, true> | |
394 | +{ | |
395 | + template<typename _tRes, typename _tExt, typename = _tExt> | |
396 | + YB_ATTR_nodiscard YB_PURE static inline _tRes | |
397 | + extended_plus(const _type& x, const _type& y) | |
398 | + { | |
399 | + _type r; | |
400 | + | |
401 | + return !__builtin_add_overflow(x, y, &r) ? _tRes(r) | |
402 | + : _tRes(_tExt(x) + _tExt(y)); | |
403 | + } | |
404 | + template<typename _tRes, typename _tExt, typename = _tExt, class _tAlloc> | |
405 | + YB_ATTR_nodiscard YB_PURE static inline _tRes | |
406 | + extended_plus(const _type& x, const _type& y, const _tAlloc& a) | |
407 | + { | |
408 | + _type r; | |
409 | + | |
410 | + return !__builtin_add_overflow(x, y, &r) | |
411 | + ? ystdex::make_obj_using_allocator<_tRes>(a, r) | |
412 | + : ystdex::make_obj_using_allocator<_tRes>(a, _tExt(x) + _tExt(y)); | |
413 | + } | |
414 | +}; | |
415 | + | |
416 | +template<typename _type> | |
417 | +struct ext_plus<_type, true, true> | |
418 | +{ | |
419 | + using limits_t = std::numeric_limits<_type>; | |
420 | + | |
421 | + template<typename _tRes, typename _tExt, typename _tExt2> | |
422 | + YB_ATTR_nodiscard YB_PURE static inline _tRes | |
423 | + extended_plus(const _type& x, const _type& y) | |
424 | + { | |
425 | + _type r; | |
426 | + | |
427 | + if(!__builtin_add_overflow(x, y, &r)) | |
428 | + return _tRes(r); | |
429 | + return x > 0 && y > limits_t::max() - x ? _tRes(_tExt(x) + _tExt(y)) | |
430 | + : _tRes(_tExt2(x) + _tExt2(y)); | |
431 | + } | |
432 | + template<typename _tRes, typename _tExt, typename _tExt2, class _tAlloc> | |
433 | + YB_ATTR_nodiscard YB_PURE static inline _tRes | |
434 | + extended_plus(const _type& x, const _type& y, const _tAlloc& a) | |
435 | + { | |
436 | + _type r; | |
437 | + | |
438 | + if(!__builtin_add_overflow(x, y, &r)) | |
439 | + return ystdex::make_obj_using_allocator<_tRes>(a, r); | |
440 | + return x > 0 && y > limits_t::max() - x | |
441 | + ? ystdex::make_obj_using_allocator<_tRes>(a, _tExt(x) + _tExt(y)) | |
442 | + : ystdex::make_obj_using_allocator<_tRes>(a, _tExt2(x) + _tExt2(y)); | |
443 | + } | |
444 | +}; | |
445 | +#endif | |
446 | + | |
447 | + | |
448 | +template<typename _type, bool = std::numeric_limits<_type>::is_signed, | |
449 | + bool = __has_builtin(__builtin_sub_overflow) && is_integral<_type>{}> | |
450 | +struct ext_minus; | |
451 | + | |
452 | +template<typename _type> | |
453 | +struct ext_minus<_type, false, false> | |
454 | +{ | |
455 | + // XXX: This is efficient enough to avoid builtins. | |
456 | + template<typename _tRes, typename _tExt, typename = _tExt> | |
457 | + YB_ATTR_nodiscard YB_PURE static inline _tRes | |
458 | + extended_minus(const _type& x, const _type& y) | |
459 | + { | |
460 | + return y <= x ? _tRes(x - y) : _tRes(_tExt(x) - _tExt(y)); | |
461 | + } | |
462 | + template<typename _tRes, typename _tExt, typename = _tExt, class _tAlloc> | |
463 | + YB_ATTR_nodiscard YB_PURE static inline _tRes | |
464 | + extended_minus(const _type& x, const _type& y, const _tAlloc& a) | |
465 | + { | |
466 | + return y <= x ? ystdex::make_obj_using_allocator<_tRes>(a, x - y) | |
467 | + : ystdex::make_obj_using_allocator<_tRes>(a, _tExt(x) - _tExt(y)); | |
468 | + } | |
469 | +}; | |
470 | + | |
471 | +template<typename _type> | |
472 | +struct ext_minus<_type, true, false> | |
473 | +{ | |
474 | + using limits_t = std::numeric_limits<_type>; | |
475 | + | |
476 | + template<typename _tRes, typename _tExt, typename _tExt2> | |
477 | + YB_ATTR_nodiscard YB_PURE static inline _tRes | |
478 | + extended_minus(const _type& x, const _type& y) | |
479 | + { | |
480 | + if((x >= 0 && (YB_UNLIKELY(y == limits_t::min()) | |
481 | + || -y > limits_t::max() - x))) | |
482 | + return _tRes(_tExt(x) - _tExt(y)); | |
483 | + return x < 0 && -y < limits_t::min() - x ? _tRes(_tExt2(x) - _tExt2(y)) | |
484 | + : _tRes(x - y); | |
485 | + } | |
486 | + template<typename _tRes, typename _tExt, typename _tExt2, class _tAlloc> | |
487 | + YB_ATTR_nodiscard YB_PURE static inline _tRes | |
488 | + extended_minus(const _type& x, const _type& y, const _tAlloc& a) | |
489 | + { | |
490 | + if((x >= 0 && (YB_UNLIKELY(y == limits_t::min()) | |
491 | + || -y > limits_t::max() - x))) | |
492 | + return | |
493 | + ystdex::make_obj_using_allocator<_tRes>(a, _tExt(x) - _tExt(y)); | |
494 | + return x < 0 && -y < limits_t::min() - x | |
495 | + ? ystdex::make_obj_using_allocator<_tRes>(a, _tExt2(x) - _tExt2(y)) | |
496 | + : ystdex::make_obj_using_allocator<_tRes>(a, x - y); | |
497 | + } | |
498 | +}; | |
499 | + | |
500 | +#if __has_builtin(__builtin_sub_overflow) | |
501 | +template<typename _type> | |
502 | +// XXX: This is efficient enough to avoid builtins. | |
503 | +struct ext_minus<_type, false, true> : ext_minus<_type, false, false> | |
504 | +{}; | |
505 | + | |
506 | +template<typename _type> | |
507 | +struct ext_minus<_type, true, true> | |
508 | +{ | |
509 | + using limits_t = std::numeric_limits<_type>; | |
510 | + | |
511 | + template<typename _tRes, typename _tExt, typename _tExt2> | |
512 | + YB_ATTR_nodiscard YB_PURE static inline _tRes | |
513 | + extended_minus(const _type& x, const _type& y) | |
514 | + { | |
515 | + _type r; | |
516 | + | |
517 | + if(!__builtin_sub_overflow(x, y, &r)) | |
518 | + return _tRes(r); | |
519 | + return YB_UNLIKELY(y == limits_t::min()) | |
520 | + || (x > 0 && -y > limits_t::max() - x) | |
521 | + ? _tRes(_tExt(x) - _tExt(y)) : _tRes(_tExt2(x) - _tExt2(y)); | |
522 | + } | |
523 | + template<typename _tRes, typename _tExt, typename _tExt2, class _tAlloc> | |
524 | + YB_ATTR_nodiscard YB_PURE static inline _tRes | |
525 | + extended_minus(const _type& x, const _type& y, const _tAlloc& a) | |
526 | + { | |
527 | + _type r; | |
528 | + | |
529 | + if(!__builtin_sub_overflow(x, y, &r)) | |
530 | + return ystdex::make_obj_using_allocator<_tRes>(a, r); | |
531 | + return YB_UNLIKELY(y == limits_t::min()) | |
532 | + || (x > 0 && -y > limits_t::max() - x) | |
533 | + ? ystdex::make_obj_using_allocator<_tRes>(a, _tExt(x) - _tExt(y)) | |
534 | + : ystdex::make_obj_using_allocator<_tRes>(a, _tExt2(x) - _tExt2(y)); | |
535 | + } | |
536 | +}; | |
537 | +#endif | |
538 | + | |
539 | + | |
540 | +template<typename _type, | |
541 | + bool = __has_builtin(__builtin_mul_overflow) && is_integral<_type>{}> | |
542 | +struct ext_multiply; | |
543 | + | |
544 | +template<typename _type> | |
545 | +struct ext_multiply<_type, false> | |
546 | +{ | |
547 | + using limits_t = std::numeric_limits<_type>; | |
548 | + | |
549 | + template<typename _tRes, typename _tExt> | |
550 | + YB_ATTR_nodiscard YB_PURE static inline _tRes | |
551 | + extended_multiply(const _type& x, const _type& y) | |
552 | + { | |
553 | + const _tExt r(_tExt(x) * _tExt(y)); | |
554 | + | |
555 | + return r <= _tExt(limits_t::max()) ? _tRes(_type(r)) : _tRes(r); | |
556 | + } | |
557 | + template<typename _tRes, typename _tExt, class _tAlloc> | |
558 | + YB_ATTR_nodiscard YB_PURE static inline _tRes | |
559 | + extended_multiply(const _type& x, const _type& y, const _tAlloc& a) | |
560 | + { | |
561 | + const _tExt r(_tExt(x) * _tExt(y)); | |
562 | + | |
563 | + return r <= _tExt(limits_t::max()) ? ystdex::make_obj_using_allocator< | |
564 | + _tRes>(a, _type(r)) : ystdex::make_obj_using_allocator<_tRes>(a, r); | |
565 | + } | |
566 | +}; | |
567 | + | |
568 | +#if __has_builtin(__builtin_mul_overflow) | |
569 | +template<typename _type> | |
570 | +struct ext_multiply<_type, true> | |
571 | +{ | |
572 | + template<typename _tRes, typename _tExt> | |
573 | + YB_ATTR_nodiscard YB_PURE static inline _tRes | |
574 | + extended_multiply(const _type& x, const _type& y) | |
575 | + { | |
576 | + _type r; | |
577 | + | |
578 | + return !__builtin_mul_overflow(x, y, &r) ? _tRes(r) | |
579 | + : _tRes(_tExt(x) * _tExt(y)); | |
580 | + } | |
581 | + template<typename _tRes, typename _tExt, class _tAlloc> | |
582 | + YB_ATTR_nodiscard YB_PURE static inline _tRes | |
583 | + extended_multiply(const _type& x, const _type& y, const _tAlloc& a) | |
584 | + { | |
585 | + _type r; | |
586 | + | |
587 | + return !__builtin_mul_overflow(x, y, &r) ? _tRes(r) | |
588 | + : ystdex::make_obj_using_allocator<_tRes>(a, _tExt(x) * _tExt(y)); | |
589 | + } | |
590 | +}; | |
591 | +#endif | |
592 | +//!@} | |
593 | + | |
594 | + | |
595 | +//! \warning 非虚析构。 | |
596 | +struct ext_noreturn | |
597 | +{ | |
598 | + template<typename _type> | |
599 | + YB_NORETURN friend inline _type | |
600 | + operator+(const _type&, const _type&) | |
601 | + { | |
602 | + YB_ASSUME(false); | |
603 | + } | |
604 | + | |
605 | + template<typename _type> | |
606 | + YB_NORETURN friend inline _type | |
607 | + operator-(const _type&, const _type&) | |
608 | + { | |
609 | + YB_ASSUME(false); | |
610 | + } | |
611 | + | |
612 | + template<typename _type> | |
613 | + YB_NORETURN friend inline _type | |
614 | + operator*(const _type&, const _type&) | |
615 | + { | |
616 | + YB_ASSUME(false); | |
617 | + } | |
618 | + | |
619 | + template<typename _type> | |
620 | + YB_NORETURN inline | |
621 | + operator _type() | |
622 | + { | |
623 | + YB_ASSUME(false); | |
624 | + } | |
625 | +}; | |
626 | + | |
627 | + | |
628 | +struct ext_overflow final : ext_noreturn | |
629 | +{ | |
630 | + template<typename _type> | |
631 | + inline | |
632 | + ext_overflow(const _type&) | |
633 | + { | |
634 | + throw_overflow_error(); | |
635 | + } | |
636 | +}; | |
637 | + | |
638 | + | |
639 | +struct ext_underflow final : ext_noreturn | |
640 | +{ | |
641 | + template<typename _type> | |
642 | + inline | |
643 | + ext_underflow(const _type&) | |
644 | + { | |
645 | + throw_underflow_error(); | |
646 | + } | |
647 | +}; | |
648 | + | |
649 | +} // namespace details; | |
650 | + | |
651 | +/*! | |
652 | +\note 不使用 common_type_t 以允许另行单独检查转换时可能的溢出。 | |
653 | +\exception std::overflow 上溢:转换的中间计算或结果的不能被最大值表示。 | |
654 | +*/ | |
655 | +//!@{ | |
656 | +//! \exception std::overflow 下溢:转换的中间计算或结果的不能被最小值表示。 | |
657 | +//!@{ | |
658 | +//! \brief 检查溢出的加法。 | |
659 | +template<typename _type, typename = enable_if_t<!is_unbounded_number<_type>{}>> | |
660 | +YB_ATTR_nodiscard YB_PURE _type | |
661 | +checked_plus(const _type& x, const _type& y) | |
662 | +{ | |
663 | + return details::ext_plus<_type>::template extended_plus<_type, | |
664 | + details::ext_overflow, details::ext_underflow>(x, y); | |
665 | +} | |
666 | + | |
667 | +//! \brief 检查溢出的减法。 | |
668 | +template<typename _type, typename = enable_if_t<!is_unbounded_number<_type>{}>> | |
669 | +YB_ATTR_nodiscard YB_PURE _type | |
670 | +checked_minus(const _type& x, const _type& y) | |
671 | +{ | |
672 | + return details::ext_minus<_type>::template extended_minus<_type, | |
673 | + details::ext_overflow, details::ext_underflow>(x, y); | |
674 | +} | |
675 | +//!@} | |
676 | + | |
677 | +//! \brief 检查溢出的乘法。 | |
678 | +template<typename _type, typename = enable_if_t<!is_unbounded_number<_type>{}>> | |
679 | +YB_ATTR_nodiscard YB_PURE _type | |
680 | +checked_multiply(const _type& x, const _type& y) | |
681 | +{ | |
682 | + return details::ext_multiply<_type>::template extended_minus<_type, | |
683 | + details::ext_overflow>(x, y); | |
684 | +} | |
685 | +//!@} | |
686 | + | |
687 | + | |
688 | +/*! | |
689 | +\pre 静态断言:第三模板参数应具有 \c numeric_limits 特化且为有界类型。 | |
690 | +\return 指定第一参数类型的保存结果的值。 | |
691 | +\sa ystdex::make_obj_using_allocator | |
692 | + | |
693 | +第一模板参数指定保存可通过不同结果类型初始化的结果类型,如 any 。 | |
694 | +第二模板参数指定保存扩展类型。 | |
695 | +最后一个模板参数是操作数的类型。 | |
696 | +前两个函数参数指定操作数。 | |
697 | +可选的第三个函数参数指定分配器。 | |
698 | +计算时,结果被检查以确定是否可在操作数类型的值域中表示。 | |
699 | +若可以表示,则中间结果类型是操作数的类型;否则,中间结果类型是扩展类型。 | |
700 | +结果是结果类型通过中间结果类型的中间值显式初始化得到的值。 | |
701 | +若指定分配器,使用 ystdex::make_obj_using_allocator 初始化结果; | |
702 | + 否则,直接初始化结果。 | |
703 | +*/ | |
704 | +//!@{ | |
705 | +/*! | |
706 | +\sa extend_additive_overflow | |
707 | +\sa extend_additive_underflow | |
708 | + | |
709 | +第二模板参数指定保存可能上溢时的扩展类型。 | |
710 | +第三模板参数指定保存可能下溢时的扩展类型。 | |
711 | +为避免有符号整数溢出的未定义行为或错误的计算结果, | |
712 | + 使用 extend_additive_overflow 等方式确定扩展类型能保存任意计算结果。 | |
713 | +*/ | |
714 | +//!@{ | |
715 | +/*! | |
716 | +\brief 可扩展中间结果类型的加法。 | |
717 | + | |
718 | +计算函数参数指定的数值作为乘数的加法。 | |
719 | +若操作数是整数类型,则可选使用实现支持的 \c __builtin_add_overflow 。 | |
720 | +*/ | |
721 | +//!@{ | |
722 | +template<typename _tRes, typename _tExt, typename _tExt2 = _tExt, | |
723 | + typename _type, typename = enable_if_t<!is_unbounded_number<_type>{}>> | |
724 | +YB_ATTR_nodiscard YB_PURE inline auto | |
725 | +extended_plus(const _type& x, const _type& y) | |
726 | + -> enable_if_t<is_constructible<_tRes, decltype(x + y)>{}, _tRes> | |
727 | +{ | |
728 | + return details::ext_plus<_type>::template | |
729 | + extended_plus<_tRes, _tExt, _tExt2>(x, y); | |
730 | +} | |
731 | +template<typename _tRes, typename _tExt, typename _tExt2 = _tExt, | |
732 | + typename _type, class _tAlloc, | |
733 | + typename = enable_if_t<!is_unbounded_number<_type>{}>> | |
734 | +YB_ATTR_nodiscard YB_PURE inline auto | |
735 | +extended_plus(const _type& x, const _type& y, const _tAlloc& a) | |
736 | + -> enable_if_t<is_constructible<_tRes, decltype(x * y)>{}, _tRes> | |
737 | +{ | |
738 | + return details::ext_plus<_type>::template | |
739 | + extended_plus<_tRes, _tExt, _tExt2>(x, y, a); | |
740 | +} | |
741 | +//!@} | |
742 | + | |
743 | +/*! | |
744 | +\brief 可扩展中间结果类型的减法。 | |
745 | +\sa extend_additive_overflow | |
746 | + | |
747 | +计算函数参数指定的数值作为乘数的减法。 | |
748 | +若操作数是整数类型,则可选使用实现支持的 \c __builtin_sub_overflow 。 | |
749 | +*/ | |
750 | +//!@{ | |
751 | +template<typename _tRes, typename _tExt, typename _tExt2 = _tExt, | |
752 | + typename _type, typename = enable_if_t<!is_unbounded_number<_type>{}>> | |
753 | +YB_ATTR_nodiscard YB_PURE inline auto | |
754 | +extended_minus(const _type& x, const _type& y) | |
755 | + -> enable_if_t<is_constructible<_tRes, decltype(x + y)>{}, _tRes> | |
756 | +{ | |
757 | + return details::ext_minus<_type>::template | |
758 | + extended_minus<_tRes, _tExt, _tExt2>(x, y); | |
759 | +} | |
760 | +template<typename _tRes, typename _tExt, typename _tExt2 = _tExt, | |
761 | + typename _type, class _tAlloc, | |
762 | + typename = enable_if_t<!is_unbounded_number<_type>{}>> | |
763 | +YB_ATTR_nodiscard YB_PURE inline auto | |
764 | +extended_minus(const _type& x, const _type& y, const _tAlloc& a) | |
765 | + -> enable_if_t<is_constructible<_tRes, decltype(x * y)>{}, _tRes> | |
766 | +{ | |
767 | + return details::ext_minus<_type>::template | |
768 | + extended_minus<_tRes, _tExt, _tExt2>(x, y, a); | |
769 | +} | |
770 | +//!@} | |
771 | +//!@} | |
772 | + | |
773 | +/*! | |
774 | +\brief 可扩展中间结果类型的乘法。 | |
775 | +\sa extend_product | |
776 | + | |
777 | +计算函数参数指定的数值作为乘数的乘法。 | |
778 | +若操作数是整数类型,则可选使用实现支持的 \c __builtin_mul_overflow 。 | |
779 | +为避免有符号整数溢出的未定义行为或错误的计算结果, | |
780 | + 使用 extend_product 等方式确定扩展类型能保存任意计算结果。 | |
781 | +*/ | |
782 | +//!@{ | |
783 | +template<typename _tRes, typename _tExt, typename _type, | |
784 | + typename = enable_if_t<!is_unbounded_number<_type>{}>> | |
785 | +YB_ATTR_nodiscard YB_PURE inline auto | |
786 | +extended_multiply(const _type& x, const _type& y) | |
787 | + -> enable_if_t<is_constructible<_tRes, decltype(x * y)>{}, _tRes> | |
788 | +{ | |
789 | + return details::ext_multiply<_type>::template | |
790 | + extended_multiply<_tRes, _tExt>(x, y); | |
791 | +} | |
792 | +template<typename _tRes, typename _tExt, typename _type, class _tAlloc, | |
793 | + typename = enable_if_t<!is_unbounded_number<_type>{}>> | |
794 | +YB_ATTR_nodiscard YB_PURE inline auto | |
795 | +extended_multiply(const _type& x, const _type& y, const _tAlloc& a) | |
796 | + -> enable_if_t<is_constructible<_tRes, decltype(x * y)>{}, _tRes> | |
797 | +{ | |
798 | + return details::ext_multiply<_type>::template | |
799 | + extended_multiply<_tRes, _tExt>(x, y, a); | |
800 | +} | |
801 | +//!@} | |
802 | +//!@} | |
803 | + | |
804 | +/*! | |
805 | +\brief 检查模板参数指定的值作为乘数的整数乘法结果。 | |
806 | +\return 在结果类型中能表示的积。 | |
807 | +\throw std::overflow 上溢:结果超出可表示的范围上界。 | |
808 | +\throw std::underflow 下溢:结果超出可表示的范围下界。 | |
809 | +*/ | |
810 | +// XXX: This does not use %std::intmax_t as the multiplier constant type because | |
811 | +// this can have smaller than %__int128_t besides the signedness problem. Note | |
812 | +// libstdc++ in GNU extension modes and libc++ also treats %__int128_t as | |
813 | +// integral types, while libstdc++ in the standard modes does not, see | |
814 | +// https://quuxplusone.github.io/blog/2019/02/28/is-int128-integral/. Just use | |
815 | +// it as-is here for simplicity. | |
816 | +template<typename _tDst, _tDst _vMul, typename _tSrc> | |
817 | +auto | |
818 | +checked_constant_multiply(_tSrc x) -> decltype(x * _vMul) | |
819 | +{ | |
820 | + // XXX: This should be usable for all integer-like types, not only the | |
821 | + // fundamental types. | |
822 | +#if false | |
823 | + static_assert(std::is_integral<_tDst>(), "Invalid destination type found."); | |
824 | + static_assert(std::is_integral<_tSrc>(), "Invalid source type found."); | |
825 | +#endif | |
826 | + using limits_t = std::numeric_limits<_tDst>; | |
827 | + const auto r(x * _vMul); | |
828 | + using _tRes = decltype(r); | |
829 | + using limits_r_t = std::numeric_limits<_tRes>; | |
830 | + | |
831 | + return details::checked_conv_int<_tDst, _tRes, (std::float_t( | |
832 | + limits_t::max()) < std::float_t(limits_r_t::max())), | |
833 | + (std::float_t(limits_t::min()) > std::float_t(limits_r_t::min()))>()(r); | |
834 | +} | |
835 | +//!@} | |
836 | + | |
837 | +} // namespace ystdex; | |
838 | + | |
839 | +#endif | |
840 | + |
@@ -1,5 +1,5 @@ | ||
1 | 1 | /* |
2 | - © 2015-2016, 2018-2023 FrankHB. | |
2 | + © 2015-2016, 2018-2024 FrankHB. | |
3 | 3 | |
4 | 4 | This file is part of the YSLib project, and may only be used, modified, |
5 | 5 | and distributed under the terms of the YSLib project license. |
@@ -10,13 +10,13 @@ | ||
10 | 10 | /*! \file bit.hpp |
11 | 11 | \ingroup YStandardEx |
12 | 12 | \brief 位操作。 |
13 | -\version r1428 | |
13 | +\version r1432 | |
14 | 14 | \author FrankHB <frankhb1989@gmail.com> |
15 | 15 | \since build 245 |
16 | 16 | \par 创建时间: |
17 | 17 | 2021-12-18 22:57:19 +0800 |
18 | 18 | \par 修改时间: |
19 | - 2023-12-20 20:45 +0800 | |
19 | + 2024-04-06 15:23 +0800 | |
20 | 20 | \par 文本编码: |
21 | 21 | UTF-8 |
22 | 22 | \par 模块名称: |
@@ -40,7 +40,7 @@ | ||
40 | 40 | // std::uint_fast8_t, std::uint64_t, yconstraint; |
41 | 41 | #include "meta.hpp" // for CHAR_BIT, byte, enable_if_unsigned_t, size_t, |
42 | 42 | // size_t_; |
43 | -#include <limits> // for std::numeric_limits; | |
43 | +#include <libdefect/limits.hpp> // for std::numeric_limits (with fixes); | |
44 | 44 | // NOTE: See https://docs.microsoft.com/cpp/visual-cpp-language-conformance and |
45 | 45 | // https://docs.microsoft.com/cpp/preprocessor/predefined-macros. |
46 | 46 | #if (YB_IMPL_MSCPP >= 1925 && _MSVC_LANG >= 201907L) \ |
@@ -478,7 +478,7 @@ | ||
478 | 478 | yimpl(enable_if_unsigned_t)<_type, size_t> |
479 | 479 | floor_lb(_type x) ynothrowv |
480 | 480 | { |
481 | - return details::floor_lb_w(x, size_t_<sizeof(x) * CHAR_BIT>()); | |
481 | + return details::floor_lb_w(x, bit_width_t<_type>()); | |
482 | 482 | } |
483 | 483 | |
484 | 484 | /*! |
@@ -490,7 +490,7 @@ | ||
490 | 490 | yimpl(enable_if_unsigned_t)<_type, size_t> |
491 | 491 | ceiling_lb(_type x) ynothrowv |
492 | 492 | { |
493 | - return 1 + details::floor_lb_w(x - 1, size_t_<sizeof(x) * CHAR_BIT>()); | |
493 | + return 1 + details::floor_lb_w(x - 1, bit_width_t<_type>()); | |
494 | 494 | } |
495 | 495 | |
496 | 496 |
@@ -1,5 +1,5 @@ | ||
1 | 1 | /* |
2 | - © 2010-2017, 2019-2023 FrankHB. | |
2 | + © 2010-2017, 2019-2024 FrankHB. | |
3 | 3 | |
4 | 4 | This file is part of the YSLib project, and may only be used, modified, |
5 | 5 | and distributed under the terms of the YSLib project license. |
@@ -10,13 +10,13 @@ | ||
10 | 10 | /*! \file cast.hpp |
11 | 11 | \ingroup YStandardEx |
12 | 12 | \brief C++ 转换模板。 |
13 | -\version r1500 | |
13 | +\version r1503 | |
14 | 14 | \author FrankHB <frankhb1989@gmail.com> |
15 | 15 | \since build 175 |
16 | 16 | \par 创建时间: |
17 | 17 | 2010-12-15 08:13:18 +0800 |
18 | 18 | \par 修改时间: |
19 | - 2023-12-17 00:07 +0800 | |
19 | + 2024-04-06 15:27 +0800 | |
20 | 20 | \par 文本编码: |
21 | 21 | UTF-8 |
22 | 22 | \par 模块名称: |
@@ -30,7 +30,7 @@ | ||
30 | 30 | #include "type_op.hpp" // for decay_t, is_same, false_, true_, is_polymorphic, |
31 | 31 | // is_pointer, is_base_of, remove_cv_t, remove_pointer_t, and_, not_, |
32 | 32 | // have_common_nonempty_virtual_base, remove_rp, _t; |
33 | -#include <limits> // for std::numeric_limits; | |
33 | +#include <libdefect/limits.hpp> // for std::numeric_limits (with fixes); | |
34 | 34 | #include "exception.h" // for narrowing_error, std::addressof; |
35 | 35 | #include <typeinfo> // for std::bad_cast; |
36 | 36 | #include "cassert.h" // for yassume, YAssert; |
@@ -444,8 +444,8 @@ | ||
444 | 444 | |
445 | 445 | /*! |
446 | 446 | \brief 一般类型转换。 |
447 | +\tparam _tDst 目标类型。 | |
447 | 448 | \tparam _tSrc 源类型。 |
448 | -\tparam _tDst 目标类型。 | |
449 | 449 | \since build 175 |
450 | 450 | \todo 扩展接受右值引用参数。 |
451 | 451 |
@@ -0,0 +1,581 @@ | ||
1 | +/* | |
2 | + © 2015, 2018, 2019, 2021, 2024 FrankHB. | |
3 | + | |
4 | + This file is part of the YSLib project, and may only be used, modified, | |
5 | + and distributed under the terms of the YSLib project license. | |
6 | + By continuing to use, modify, or distribute this file you indicate that | |
7 | + you have read the license and understand and accept it fully. | |
8 | +*/ | |
9 | + | |
10 | +/*! \file charconv.h | |
11 | +\ingroup YStandardEx | |
12 | +\brief 数值的字符表示和转换操作。 | |
13 | +\version r1461 | |
14 | +\author FrankHB <frankhb1989@gmail.com> | |
15 | +\since build 983 | |
16 | +\par 创建时间: | |
17 | + 2024-04-14 21:16:46 +0800 | |
18 | +\par 修改时间: | |
19 | + 2024-04-19 22:25 +0800 | |
20 | +\par 文本编码: | |
21 | + UTF-8 | |
22 | +\par 模块名称: | |
23 | + YStandardEx::CharacterConversion | |
24 | +*/ | |
25 | + | |
26 | + | |
27 | +#ifndef YB_INC_ystdex_charconv_h_ | |
28 | +#define YB_INC_ystdex_charconv_h_ 1 | |
29 | + | |
30 | +#include "arithmetic.hpp" // for internal "cstdint.hpp" (implying | |
31 | +// <libdefect/limits.hpp>), make_width_int, std::numeric_limits (with fixes), | |
32 | +// size_t, YB_VerifyIterator, yconstraint, ystdex::make_reverse_iterator, | |
33 | +// enable_if_rep_in_digits10, ystdex::upow; | |
34 | +#include <numeric> // for std::accumulate; | |
35 | + | |
36 | +namespace ystdex | |
37 | +{ | |
38 | + | |
39 | +//! \pre 静态断言:整数宽度非零且为 byte 类型宽度的整数倍。 | |
40 | +//!@{ | |
41 | +/*! | |
42 | +\brief 使用迭代器对指定的范围中的字节表示的序列构造无符号整数。 | |
43 | +\pre 范围中的迭代器可解引用。 | |
44 | +\since build 603 | |
45 | +*/ | |
46 | +template<size_t _vWidth, typename _tIn> | |
47 | +YB_ATTR_nodiscard YB_PURE typename make_width_int<_vWidth>::unsigned_type | |
48 | +pack_uint(_tIn first, _tIn last) ynothrowv | |
49 | +{ | |
50 | + static_assert(_vWidth != 0 && _vWidth % std::numeric_limits< | |
51 | + unsigned char>::digits == 0, "Invalid integer width found."); | |
52 | + using utype = typename make_width_int<_vWidth>::unsigned_type; | |
53 | + | |
54 | + YB_VerifyIterator(first); | |
55 | + return std::accumulate(first, last, utype(), | |
56 | + [] YB_LAMBDA_ANNOTATE((utype x, byte y), ynothrow, pure){ | |
57 | + return | |
58 | + utype(x << std::numeric_limits<unsigned char>::digits | utype(y)); | |
59 | + }); | |
60 | +} | |
61 | + | |
62 | +/*! | |
63 | +\brief 分解无符号整数到迭代器对指定的字节范围。 | |
64 | +\pre 断言:范围中的迭代器可解引用。 | |
65 | +\since build 604 | |
66 | +*/ | |
67 | +template<size_t _vWidth, typename _tOut> | |
68 | +void | |
69 | +unpack_uint(typename ystdex::make_width_int<_vWidth>::unsigned_type value, | |
70 | + _tOut result) ynothrow | |
71 | +{ | |
72 | + static_assert(_vWidth != 0 && _vWidth % std::numeric_limits< | |
73 | + unsigned char>::digits == 0, "Invalid integer width found."); | |
74 | + auto n(_vWidth); | |
75 | + | |
76 | + while(!(_vWidth < (n -= std::numeric_limits<unsigned char>::digits))) | |
77 | + { | |
78 | + YB_VerifyIterator(result); | |
79 | + *result = byte(value >> n); | |
80 | + ++result; | |
81 | + } | |
82 | +} | |
83 | +//!@} | |
84 | + | |
85 | +//! \pre 指针参数非空。 | |
86 | +//!@{ | |
87 | +/*! | |
88 | +\brief 从字节缓冲区读取指定宽的大端序无符号整数。 | |
89 | +\since build 623 | |
90 | +*/ | |
91 | +template<size_t _vWidth> | |
92 | +YB_ATTR_nodiscard YB_NONNULL(1) YB_PURE inline | |
93 | + typename make_width_int<_vWidth>::unsigned_type | |
94 | +read_uint_be(const byte* buf) ynothrowv | |
95 | +{ | |
96 | + yconstraint(buf); | |
97 | + return ystdex::pack_uint<_vWidth>(buf, | |
98 | + buf + _vWidth / std::numeric_limits<unsigned char>::digits); | |
99 | +} | |
100 | + | |
101 | +//! \since build 608 | |
102 | +//!@{ | |
103 | +//! \brief 从字节缓冲区读取指定宽的小端序无符号整数。 | |
104 | +template<size_t _vWidth> | |
105 | +YB_ATTR_nodiscard YB_NONNULL(1) YB_PURE inline | |
106 | + typename make_width_int<_vWidth>::unsigned_type | |
107 | +read_uint_le(const byte* buf) ynothrowv | |
108 | +{ | |
109 | + yconstraint(buf); | |
110 | + return ystdex::pack_uint<_vWidth>(ystdex::make_reverse_iterator( | |
111 | + buf + _vWidth / std::numeric_limits<unsigned char>::digits), | |
112 | + ystdex::make_reverse_iterator(buf)); | |
113 | +} | |
114 | + | |
115 | +/*! | |
116 | +\brief 向字节缓冲区写入指定宽的大端序无符号整数。 | |
117 | +\since build 623 | |
118 | +*/ | |
119 | +template<size_t _vWidth> | |
120 | +YB_NONNULL(1) inline void | |
121 | +write_uint_be(byte* buf, typename make_width_int<_vWidth>::unsigned_type val) | |
122 | + ynothrowv | |
123 | +{ | |
124 | + yconstraint(buf); | |
125 | + ystdex::unpack_uint<_vWidth>(val, buf); | |
126 | +} | |
127 | + | |
128 | +//! \brief 向字节缓冲区写入指定宽的小端序无符号整数。 | |
129 | +template<size_t _vWidth> | |
130 | +YB_NONNULL(1) inline void | |
131 | +write_uint_le(byte* buf, typename make_width_int<_vWidth>::unsigned_type val) | |
132 | + ynothrowv | |
133 | +{ | |
134 | + yconstraint(buf); | |
135 | + ystdex::unpack_uint<_vWidth>(val, ystdex::make_reverse_iterator(buf | |
136 | + + _vWidth / std::numeric_limits<unsigned char>::digits)); | |
137 | +} | |
138 | +//!@} | |
139 | +//!@} | |
140 | + | |
141 | + | |
142 | +//! \since build 983 | |
143 | +//!@{ | |
144 | +/*! | |
145 | +\ingroup traits | |
146 | +\brief 倍增位数的数值写入特征。 | |
147 | + | |
148 | +第一参数指定正整数值的位宽。 | |
149 | +第二参数指定整数类型。 | |
150 | +第三参数指定半数位宽的写入数值特征。 | |
151 | +第三参数应具有本特征相同种类的相同名称的可公开访问的成员。 | |
152 | +*/ | |
153 | +template<size_t _vLen, typename _type, class _tHalfTraits> | |
154 | +struct double_digits_write_traits | |
155 | +{ | |
156 | + using value_type = _type; | |
157 | + using half_traits = _tHalfTraits; | |
158 | + | |
159 | + //! \brief 除数:表示写入时使用的数值进位制。 | |
160 | + static yconstexpr const value_type divisor | |
161 | + = value_type(half_traits::divisor) * half_traits::divisor; | |
162 | + | |
163 | + /*! | |
164 | + \brief 写入第二参数的值的表示到第一参数指定的起始位置的缓冲区。 | |
165 | + | |
166 | + 第二参数应支持相同类型操作数的乘法、除法和模操作,且乘法操作结果可和值比较; | |
167 | + 但特化的实现可提供不同的 \c write 实现,不要求支持这些操作。 | |
168 | + */ | |
169 | + template<typename _tRandom> | |
170 | + YB_ATTR_always_inline static _tRandom | |
171 | + write(_tRandom buf, value_type val) ynothrowv | |
172 | + { | |
173 | + using half_type = typename half_traits::value_type; | |
174 | + | |
175 | + yconstraint(val < divisor * divisor); | |
176 | + yunseq(half_traits::write(buf, half_type(val / divisor)), | |
177 | + half_traits::write(buf + _vLen / 2, half_type(val % divisor))); | |
178 | + return buf + _vLen; | |
179 | + } | |
180 | +}; | |
181 | + | |
182 | + | |
183 | +/*! | |
184 | +\ingroup transformation_traits | |
185 | +\brief 取表示参数指定十进制数值位数需要的最小无符号整数类型。 | |
186 | + | |
187 | +直接写入的 \c write 成员支持 8 、16 、32 和 64 位整数,可选支持 128 位整数。 | |
188 | +不在支持的类型中可表示的结果是非整数。 | |
189 | +*/ | |
190 | +template<size_t _vLen> | |
191 | +using decimal_min_uint_t = conditional_t<_vLen <= 2, std::uint_fast8_t, | |
192 | + conditional_t<_vLen <= 4, std::uint16_t, conditional_t<_vLen <= 8, | |
193 | + std::uint32_t, conditional_t<_vLen <= 19, std::uint64_t, | |
194 | +#if YB_Use_int128 > 0 | |
195 | + conditional_t<_vLen <= 38, uint128_t, yimpl(void)> | |
196 | +#else | |
197 | + yimpl(void) | |
198 | +#endif | |
199 | + >>>>; | |
200 | + | |
201 | + | |
202 | +namespace details | |
203 | +{ | |
204 | + | |
205 | +template<size_t, typename> | |
206 | +struct decimal_write_traits; | |
207 | + | |
208 | +template<typename _type> | |
209 | +struct decimal_write_traits<1, _type> | |
210 | +{ | |
211 | + using value_type = _type; | |
212 | +}; | |
213 | + | |
214 | +template<typename _type> | |
215 | +struct decimal_write_traits<2, _type> | |
216 | +{ | |
217 | + using value_type = _type; | |
218 | + | |
219 | + static yconstexpr const value_type divisor = 10; | |
220 | + | |
221 | + template<typename _tRandom> | |
222 | + YB_ATTR_always_inline static _tRandom | |
223 | + write(_tRandom buf, value_type val) ynothrowv | |
224 | + { | |
225 | + yconstraint(val < divisor * divisor); | |
226 | + yunseq(buf[0] = '0' + char(val / divisor), | |
227 | + buf[1] = '0' + char(val % divisor)); | |
228 | + return buf + 2; | |
229 | + } | |
230 | +}; | |
231 | + | |
232 | +// XXX: Many '% 10000' in LLVM/Clang is not optimal. See | |
233 | +// https://bugs.llvm.org/show_bug.cgi?id=38217. No workaround is applied yet | |
234 | +// for the QoI issue. | |
235 | +template<size_t _vLen, typename _type> | |
236 | +struct decimal_write_traits | |
237 | + : double_digits_write_traits<_vLen, decimal_min_uint_t<(_vLen + 1) / 2>, | |
238 | + decimal_write_traits<(_vLen + 1) / 2, _type>> | |
239 | +{ | |
240 | + using value_type = _type; | |
241 | +}; | |
242 | + | |
243 | +#define YB_Impl_charconv_decimal_write_func_head(_n, _q) \ | |
244 | + _tRandom \ | |
245 | + _n(_tRandom buf, _type val) _q | |
246 | +#define YB_Impl_charconv_decimal_write_tmpl_vtype(_t) \ | |
247 | + typename _type = typename _t::value_type, \ | |
248 | + yimpl(typename = enable_if_rep_in_digits10<_t::width, _type>) | |
249 | + | |
250 | +template<class _tWriter, size_t _vBase, typename _tRandom, | |
251 | + YB_Impl_charconv_decimal_write_tmpl_vtype(_tWriter::traits_type)> | |
252 | +YB_Impl_charconv_decimal_write_func_head(write_decimal_base_addend, ynothrowv) | |
253 | +{ | |
254 | + static_assert(_tWriter::traits_type::width > _vBase, | |
255 | + "Invalid widths found."); | |
256 | + using write_a_t = typename _tWriter::template | |
257 | + rebind_t<_tWriter::traits_type::width - _vBase>; | |
258 | + using write_b_t = typename _tWriter::template rebind_t<_vBase>; | |
259 | + using traits_b_t = typename write_b_t::traits_type; | |
260 | + using value_b_t = typename traits_b_t::value_type; | |
261 | + | |
262 | + static yconstexpr const _type d(ystdex::upow(_type(10), _vBase)); | |
263 | + | |
264 | + return val < d ? write_b_t()(buf, value_b_t(val)) | |
265 | + : traits_b_t::write(write_a_t()(buf, typename | |
266 | + write_a_t::traits_type::value_type(val / d)), value_b_t(val % d)); | |
267 | +} | |
268 | + | |
269 | +} // namespace details; | |
270 | + | |
271 | +/*! | |
272 | +\ingroup traits | |
273 | +\brief 十进制连续数值写入特征。 | |
274 | + | |
275 | +第一参数为 decimal_min_uint_t 支持位数的正整数。 | |
276 | +*/ | |
277 | +template<size_t _vLen, typename _type = decimal_min_uint_t<_vLen>> | |
278 | +struct decimal_write_traits : details::decimal_write_traits<_vLen, _type> | |
279 | +{ | |
280 | + template<size_t _vOther> | |
281 | + using rebind_t = decimal_write_traits<_vOther>; | |
282 | + | |
283 | + static yconstexpr const size_t width = _vLen; | |
284 | +}; | |
285 | + | |
286 | + | |
287 | +/*! | |
288 | +\brief 写十进制到第一参数指定的输出随机迭代器作为起始位置的缓冲区中。 | |
289 | + | |
290 | +第一模板参数指定十进制数字的个数,即输出的最大长度。 | |
291 | +当前使用默认特征支持的特化范围是 1~17 。 | |
292 | +可能需要指定特征支持的特化范围是 19 、21 、32 、36 和 38 。 | |
293 | +这些范围可涵盖以下格式转换后的蕴含连续十进制数字序列的输出需求: | |
294 | + 不大于 64 位的二进制浮点数尾数。 | |
295 | + 113 位的二进制浮点数尾数。 | |
296 | + 128 位整数。 | |
297 | +*/ | |
298 | +//!@{ | |
299 | +template<size_t _vLen, class = decimal_write_traits<_vLen>> | |
300 | +struct decimal_write; | |
301 | + | |
302 | +#define YB_Impl_charconv_decimal_write_tmpl_head(_v) \ | |
303 | + template<class _tTraits> \ | |
304 | + struct decimal_write<_v, _tTraits> \ | |
305 | + { \ | |
306 | + using traits_type = _tTraits; \ | |
307 | + template<size_t _vOther> \ | |
308 | + using rebind_t = decimal_write<_vOther, \ | |
309 | + typename traits_type::template rebind_t<_vOther>>; | |
310 | + | |
311 | +#define YB_Impl_charconv_decimal_write_head(_v) \ | |
312 | + YB_Impl_charconv_decimal_write_tmpl_head(_v) \ | |
313 | + template<typename _tRandom, \ | |
314 | + YB_Impl_charconv_decimal_write_tmpl_vtype(_tTraits)> \ | |
315 | + YB_Impl_charconv_decimal_write_func_head(operator(), const ynothrowv) \ | |
316 | + { | |
317 | +#define YB_Impl_charconv_decimal_write_tail } \ | |
318 | + }; | |
319 | + | |
320 | +//! \since functors | |
321 | +//!@{ | |
322 | +YB_Impl_charconv_decimal_write_head(1) | |
323 | + yconstraint(val < 10); | |
324 | + *buf = '0' + char(val); | |
325 | + return ++buf; | |
326 | +YB_Impl_charconv_decimal_write_tail | |
327 | + | |
328 | +YB_Impl_charconv_decimal_write_head(2) | |
329 | + using write1_t = rebind_t<1>; | |
330 | + | |
331 | + yconstraint(val < 100); | |
332 | + return YB_UNLIKELY(val < 10) | |
333 | + ? write1_t()(buf, typename write1_t ::traits_type::value_type(val)) | |
334 | + : _tTraits::write(buf, typename _tTraits::value_type(val)); | |
335 | +YB_Impl_charconv_decimal_write_tail | |
336 | + | |
337 | +YB_Impl_charconv_decimal_write_head(3) | |
338 | + yconstraint(val < 1000); | |
339 | + return details::write_decimal_base_addend<rebind_t<3>, 2>(buf, val); | |
340 | +YB_Impl_charconv_decimal_write_tail | |
341 | + | |
342 | +YB_Impl_charconv_decimal_write_head(4) | |
343 | + using write2_t = rebind_t<2>; | |
344 | + using traits2_t = typename write2_t::traits_type; | |
345 | + using value2_t = typename traits2_t::value_type; | |
346 | + | |
347 | + yconstraint(val < 10000); | |
348 | + if(val < 100) | |
349 | + return write2_t()(buf, value2_t(val)); | |
350 | +#if true | |
351 | + // NOTE: 3-4 digits: aabb. | |
352 | + const auto aa(val / 100); | |
353 | + | |
354 | + if(aa < 10) | |
355 | + { | |
356 | + using write1_t = rebind_t<1>; | |
357 | + | |
358 | + write1_t()(buf, typename write1_t::traits_type::value_type(aa)); | |
359 | + } | |
360 | + else | |
361 | + { | |
362 | + traits2_t::write(buf, aa); | |
363 | + ++buf; | |
364 | + } | |
365 | + return traits2_t::write(++buf, val % 100); | |
366 | +#else | |
367 | + // NOTE: Any optimized implemenations shall be equivalent to this. | |
368 | + return traits2_t::write(write2_t()(buf, typename | |
369 | + write2_t::traits_type::value_type(val / 100)), value2_t(val % 100)); | |
370 | +#endif | |
371 | +YB_Impl_charconv_decimal_write_tail | |
372 | + | |
373 | +YB_Impl_charconv_decimal_write_head(5) | |
374 | + yconstraint(val < 100000); | |
375 | + return details::write_decimal_base_addend<rebind_t<5>, 4>(buf, val); | |
376 | +YB_Impl_charconv_decimal_write_tail | |
377 | + | |
378 | +YB_Impl_charconv_decimal_write_head(6) | |
379 | + yconstraint(val < 1000000); | |
380 | + return details::write_decimal_base_addend<rebind_t<6>, 4>(buf, val); | |
381 | +YB_Impl_charconv_decimal_write_tail | |
382 | + | |
383 | +YB_Impl_charconv_decimal_write_head(7) | |
384 | + yconstraint(val < 10000000); | |
385 | + return details::write_decimal_base_addend<rebind_t<7>, 4>(buf, val); | |
386 | +YB_Impl_charconv_decimal_write_tail | |
387 | + | |
388 | +YB_Impl_charconv_decimal_write_head(8) | |
389 | + yconstraint(val < 100000000); | |
390 | + return details::write_decimal_base_addend<rebind_t<8>, 4>(buf, val); | |
391 | +YB_Impl_charconv_decimal_write_tail | |
392 | + | |
393 | +YB_Impl_charconv_decimal_write_head(9) | |
394 | + yconstraint(val < 1000000000); | |
395 | + return details::write_decimal_base_addend<rebind_t<9>, 8>(buf, val); | |
396 | +YB_Impl_charconv_decimal_write_tail | |
397 | + | |
398 | +YB_Impl_charconv_decimal_write_head(10) | |
399 | + yconstraint(val < 10000000009); | |
400 | + return details::write_decimal_base_addend<rebind_t<10>, 8>(buf, val); | |
401 | +YB_Impl_charconv_decimal_write_tail | |
402 | + | |
403 | +YB_Impl_charconv_decimal_write_head(11) | |
404 | + yconstraint(val < 100000000000); | |
405 | + return details::write_decimal_base_addend<rebind_t<11>, 8>(buf, val); | |
406 | +YB_Impl_charconv_decimal_write_tail | |
407 | + | |
408 | +YB_Impl_charconv_decimal_write_head(12) | |
409 | + yconstraint(val < 1000000000000); | |
410 | + return details::write_decimal_base_addend<rebind_t<12>, 8>(buf, val); | |
411 | +YB_Impl_charconv_decimal_write_tail | |
412 | + | |
413 | +YB_Impl_charconv_decimal_write_head(13) | |
414 | + yconstraint(val < 10000000000000); | |
415 | + return details::write_decimal_base_addend<rebind_t<13>, 8>(buf, val); | |
416 | +YB_Impl_charconv_decimal_write_tail | |
417 | + | |
418 | +YB_Impl_charconv_decimal_write_head(14) | |
419 | + yconstraint(val < 100000000000000); | |
420 | + return details::write_decimal_base_addend<rebind_t<14>, 8>(buf, val); | |
421 | +YB_Impl_charconv_decimal_write_tail | |
422 | + | |
423 | +YB_Impl_charconv_decimal_write_head(15) | |
424 | + yconstraint(val < 1000000000000000); | |
425 | + return details::write_decimal_base_addend<rebind_t<15>, 8>(buf, val); | |
426 | +YB_Impl_charconv_decimal_write_tail | |
427 | + | |
428 | +YB_Impl_charconv_decimal_write_head(16) | |
429 | + yconstraint(val < 10000000000000000); | |
430 | + return details::write_decimal_base_addend<rebind_t<16>, 8>(buf, val); | |
431 | +YB_Impl_charconv_decimal_write_tail | |
432 | + | |
433 | +YB_Impl_charconv_decimal_write_head(17) | |
434 | + yconstraint(val < 100000000000000000); | |
435 | + | |
436 | +#if true | |
437 | + using write1_t = rebind_t<1>; | |
438 | + using write16_t = rebind_t<16>; | |
439 | + | |
440 | + if(val < 10000000000000000) | |
441 | + return | |
442 | + write16_t()(buf, typename write16_t::traits_type::value_type(val)); | |
443 | + | |
444 | + // NOTE: This prevents 64-bit divisions with more than 32-bit divisors as | |
445 | + // possible. | |
446 | + using traits8_t = typename rebind_t<8>::traits_type; | |
447 | + using value8_t = typename traits8_t::value_type; | |
448 | + // NOTE: 17 digits. | |
449 | + const auto hi(val / 100000000); | |
450 | + const auto one(typename traits8_t::value_type(hi / 100000000)); | |
451 | + | |
452 | + write1_t()(buf, typename write1_t::traits_type::value_type(one)); | |
453 | + buf += one > 0 ? 1 : 0; | |
454 | + yunseq(traits8_t::write(buf, value8_t(hi % 100000000)), | |
455 | + traits8_t::write(buf + 8, value8_t(val % 100000000))); | |
456 | + return buf + 16; | |
457 | +#else | |
458 | + // NOTE: Any optimized implemenations shall be equivalent to this. | |
459 | + return details::write_decimal_base_addend<rebind_t<17>, 16>(buf, val); | |
460 | +#endif | |
461 | +YB_Impl_charconv_decimal_write_tail | |
462 | + | |
463 | +// XXX: The following specializations may require non-defualt traits due to | |
464 | +// probably lacking of support of integers greater than 64-bit. Nevertheless, | |
465 | +// the constant division only uses divisors representable in 64-bit. | |
466 | +// NOTE: This can be used for 64-bit unsigned integers and 55~64-bit binary | |
467 | +// floating-point mantissas. | |
468 | +YB_Impl_charconv_decimal_write_head(19) | |
469 | + using write8_t = rebind_t<8>; | |
470 | + using traits8_t = typename write8_t::traits_type; | |
471 | + using value8_t = typename traits8_t::value_type; | |
472 | + | |
473 | + if(val < 100000000) | |
474 | + return write8_t()(buf, value8_t(val)); | |
475 | + | |
476 | + const auto hi(val / 100000000); | |
477 | + | |
478 | + return traits8_t::write(hi < 100000000 ? write8_t()(buf, value8_t(hi)) | |
479 | + : traits8_t::write(write8_t()(buf, value8_t(hi / 100000000)), | |
480 | + value8_t(hi % 100000000)), value8_t(val % 100000000)); | |
481 | +YB_Impl_charconv_decimal_write_tail | |
482 | + | |
483 | +// XXX: The following specializations may require additional trait functions to | |
484 | +// support divisions wider than 64-bit. | |
485 | +// NOTE: Requires %_tTraits::div10<4> to support division of type (e.g. 128-bit | |
486 | +// unsigned integer) divided by 10000. | |
487 | +// NOTE: This can be used for 64-bit binary floating-point mantissas. | |
488 | +YB_Impl_charconv_decimal_write_head(21) | |
489 | + using write17_t = rebind_t<17>; | |
490 | + using traits4_t = typename rebind_t<4>::traits_type; | |
491 | + using value17_t = typename write17_t::traits_type::value_type; | |
492 | + | |
493 | + yconstraint(val | |
494 | + < typename _tTraits::value_type(100000000000U) * 10000000000U); | |
495 | + if(val < 100000000000000000) | |
496 | + return write17_t()(buf, value17_t(val)); | |
497 | + | |
498 | + // NOTE: 18-21 digits. | |
499 | + const auto hi(_tTraits::template div10<4>(val)); | |
500 | + | |
501 | + return traits4_t::write(write17_t()(buf, value17_t(hi)), | |
502 | + typename traits4_t::value_type(val - hi * 10000)); | |
503 | +YB_Impl_charconv_decimal_write_tail | |
504 | + | |
505 | +// NOTE: This can be used for 36-bit sequences below. | |
506 | +YB_Impl_charconv_decimal_write_head(32) | |
507 | + using write16_t = rebind_t<16>; | |
508 | + using traits16_t = typename write16_t::traits_type; | |
509 | + using value16_t = typename traits16_t::value_type; | |
510 | + | |
511 | + yconstraint(val | |
512 | + < typename _tTraits::value_type(10000000000000000) * 10000000000000000); | |
513 | + return val < 100000000000000000 ? write16_t()(buf, value16_t(val)) | |
514 | + : traits16_t::write(write16_t()(buf, value16_t(val | |
515 | + / 10000000000000000)), value16_t(val % 10000000000000000)); | |
516 | +YB_Impl_charconv_decimal_write_tail | |
517 | + | |
518 | +// NOTE: This can be used for 113-bit binary floating-point mantissas. | |
519 | +YB_Impl_charconv_decimal_write_head(36) | |
520 | + using write32_t = rebind_t<32>; | |
521 | + const auto | |
522 | + d(typename _tTraits::value_type(10000000000000000) * 10000000000000000); | |
523 | + | |
524 | + yconstraint(val < d * 10000U); | |
525 | + return val < d ? write32_t()(buf, val) : write32_t::traits_type::write( | |
526 | + rebind_t<4>()(buf, val / d), val % d); | |
527 | +YB_Impl_charconv_decimal_write_tail | |
528 | + | |
529 | +// NOTE: This can be used for 128-bit unsigned integers. | |
530 | +YB_Impl_charconv_decimal_write_head(38) | |
531 | + using write32_t = rebind_t<32>; | |
532 | + const auto | |
533 | + d(typename _tTraits::value_type(10000000000000000) * 10000000000000000); | |
534 | + | |
535 | + yconstraint(val < d * 1000000U); | |
536 | + return val < d ? write32_t()(buf, val) : write32_t::traits_type::write( | |
537 | + rebind_t<6>()(buf, val / d), val % d); | |
538 | +YB_Impl_charconv_decimal_write_tail | |
539 | +#undef YB_Impl_charconv_decimal_write_tail | |
540 | +#undef YB_Impl_charconv_decimal_write_tmpl_head | |
541 | +//!@} | |
542 | + | |
543 | +template<size_t _vLen, typename _tRandom, class _tTraits = decimal_write_traits< | |
544 | + _vLen>, YB_Impl_charconv_decimal_write_tmpl_vtype(_tTraits)> | |
545 | +YB_Impl_charconv_decimal_write_func_head(write_decimal, ynothrowv) | |
546 | +{ | |
547 | + return decimal_write<_vLen>()(buf, val); | |
548 | +} | |
549 | +#undef YB_Impl_charconv_decimal_write_tmpl_vtype | |
550 | +#undef YB_Impl_charconv_decimal_write_func_head | |
551 | +//!@} | |
552 | + | |
553 | + | |
554 | +//! \brief 向第一参数指定的缓冲区写入第二参数指定的十进制整数值。 | |
555 | +template<typename _tRandom, typename _type> | |
556 | +inline _tRandom | |
557 | +write_decimal_integer(_tRandom buf, _type val) | |
558 | +{ | |
559 | + static yconstexpr const _type d(ystdex::upow(_type(10), | |
560 | + size_t(std::numeric_limits<_type>::digits10))); | |
561 | + | |
562 | + if(val >= d) | |
563 | + { | |
564 | + using write1_t = decimal_write<1>; | |
565 | + | |
566 | + write1_t::traits_type::value_type q(val / d); | |
567 | + | |
568 | + YAssert(q > 0 && q < 10, "Invalid implemenation found."); | |
569 | + | |
570 | + write1_t()(buf, q); | |
571 | + yunseq(val %= d, ++buf); | |
572 | + } | |
573 | + return | |
574 | + ystdex::write_decimal<std::numeric_limits<_type>::digits10>(buf, val); | |
575 | +} | |
576 | +//!@} | |
577 | + | |
578 | +} // namespace ystdex; | |
579 | + | |
580 | +#endif | |
581 | + |
@@ -0,0 +1,742 @@ | ||
1 | +/* | |
2 | + © 2024 FrankHB. | |
3 | + | |
4 | + This file is part of the YSLib project, and may only be used, modified, | |
5 | + and distributed under the terms of the YSLib project license. | |
6 | + By continuing to use, modify, or distribute this file you indicate that | |
7 | + you have read the license and understand and accept it fully. | |
8 | +*/ | |
9 | + | |
10 | +/*! \file chrono.hpp | |
11 | +\ingroup YStandardEx | |
12 | +\brief ISO C++ 日期和时间接口扩展。 | |
13 | +\version r741 | |
14 | +\author FrankHB <frankhb1989@gmail.com> | |
15 | +\since build 983 | |
16 | +\par 创建时间: | |
17 | + 2024-03-22 23:53:00 +0800 | |
18 | +\par 修改时间: | |
19 | + 2024-04-13 02:25 +0800 | |
20 | +\par 文本编码: | |
21 | + UTF-8 | |
22 | +\par 模块名称: | |
23 | + YStandardEx::Chrono | |
24 | +*/ | |
25 | + | |
26 | + | |
27 | +#ifndef YB_INC_ystdex_chrono_hpp_ | |
28 | +#define YB_INC_ystdex_chrono_hpp_ 1 | |
29 | + | |
30 | +#include "type_op.hpp" // for false_, void_t, and_, is_same, enable_if, true_, | |
31 | +// is_instance_of, vseq::_a, enable_if_t, is_unsigned, or_, | |
32 | +// is_floating_point, is_class, YB_HAS_NOEXCEPT, bool_, std::declval; | |
33 | +#include "arithmetic.hpp" // for internal "cstdint.hpp" (implying | |
34 | +// <libdefect/limits.hpp>), std::numeric_limits (with fixes), | |
35 | +// is_unbounded_number, throw_underflow_error, throw_overflow_error, | |
36 | +// ystdex::checked_constant_multiply, intmax_t; | |
37 | +#include <chrono> // for std::chrono; | |
38 | +#include <ratio> // for std::ratio_mutiply, std::ratio_divide, std::nano; | |
39 | +#include "ctime.h" // for is_timespec_like; | |
40 | +#include <cmath> // for std::float_t; | |
41 | + | |
42 | +namespace ystdex | |
43 | +{ | |
44 | + | |
45 | +//! \since build 983 | |
46 | +namespace chrono | |
47 | +{ | |
48 | + | |
49 | +inline namespace cpp2011 | |
50 | +{ | |
51 | + | |
52 | +using std::chrono::duration; | |
53 | + | |
54 | +using std::chrono::time_point; | |
55 | + | |
56 | +using std::chrono::treat_as_floating_point; | |
57 | +using std::chrono::duration_values; | |
58 | + | |
59 | +using std::chrono::nanoseconds; | |
60 | +using std::chrono::microseconds; | |
61 | +using std::chrono::milliseconds; | |
62 | +using std::chrono::seconds; | |
63 | +using std::chrono::minutes; | |
64 | +using std::chrono::hours; | |
65 | + | |
66 | +using std::chrono::duration_cast; | |
67 | + | |
68 | +using std::chrono::nanoseconds; | |
69 | +using std::chrono::microseconds; | |
70 | +using std::chrono::milliseconds; | |
71 | +using std::chrono::seconds; | |
72 | +using std::chrono::minutes; | |
73 | +using std::chrono::hours; | |
74 | +using std::chrono::nanoseconds; | |
75 | +using std::chrono::nanoseconds; | |
76 | +using std::chrono::nanoseconds; | |
77 | + | |
78 | +using std::chrono::time_point_cast; | |
79 | + | |
80 | +using std::chrono::system_clock; | |
81 | +using std::chrono::steady_clock; | |
82 | +using std::chrono::high_resolution_clock; | |
83 | + | |
84 | +} // inline namespace cpp2011; | |
85 | + | |
86 | +// NOTE: This requires the support of some features of WG21 P0355R7, without | |
87 | +// some features interfering ABI stability. See | |
88 | +// https://docs.microsoft.com/cpp/visual-cpp-language-conformance, | |
89 | +// https://docs.microsoft.com/cpp/preprocessor/predefined-macros and | |
90 | +// https://learn.microsoft.com/cpp/overview/compiler-versions | |
91 | +#if (YB_IMPL_MSCPP >= 1929 && _MSC_FULL_VER >= 192930129L \ | |
92 | + && _MSVC_LANG >= 202002L) || __cplusplus >= 202002L | |
93 | +# define YB_Impl_Chrono_has_cpp20_chrono_stable true | |
94 | +#else | |
95 | +# define YB_Impl_Chrono_has_cpp20_chrono_stable false | |
96 | +#endif | |
97 | +#if YB_Impl_Chrono_has_cpp20_chrono_stable && !defined _LIBCPP_VERSION | |
98 | +# define YB_Impl_Chrono_has_cpp20_chrono_is_clock true | |
99 | +#else | |
100 | +# define YB_Impl_Chrono_has_cpp20_chrono_is_clock false | |
101 | +#endif | |
102 | + | |
103 | +namespace details | |
104 | +{ | |
105 | + | |
106 | +#if !YB_Impl_Chrono_has_cpp20_chrono_is_clock | |
107 | +template<typename, typename = void> | |
108 | +struct is_clock : false_ | |
109 | +{}; | |
110 | + | |
111 | +template<typename _type> | |
112 | +struct is_clock<_type, void_t<typename _type::rep, typename _type::period, | |
113 | + // XXX: ISO C++20 [time.traits.is.clock]/1 reuires member %time_point as a | |
114 | + // type, but Cpp17Clock requirements requires more on this type. Use its | |
115 | + // member to provide stricter check (see below). | |
116 | + typename _type::druation, typename _type::time_point::duration, | |
117 | + decltype(_type::is_steady), decltype(_type::now())>> | |
118 | + // XXX: Follows libstdc++ here for unspecified checks on ISO C++20 | |
119 | + // [time.traits.is.clock]/1. Note %_type here shall be complete, which is | |
120 | + // implied by the requirements on nested members, so potentionally | |
121 | + // overloaded '&' can be used. | |
122 | + : and_<is_same<typename _type::duration, duration<typename _type::rep, | |
123 | + typename _type::period>>, is_same<typename _type::time_point::duration, | |
124 | + typename _type::duration>, is_same<decltype(&_type::is_steady), | |
125 | + const bool*>, is_same<decltype(_type::now()), typename _type::time_point>> | |
126 | +{}; | |
127 | +#endif | |
128 | + | |
129 | +template<typename _type, typename = void> | |
130 | +struct unchecked_rep : treat_as_floating_point<_type> | |
131 | +{}; | |
132 | + | |
133 | +template<typename _type> | |
134 | +struct unchecked_rep<_type, enable_if<is_unbounded_number<_type>{}>> : true_ | |
135 | +{}; | |
136 | + | |
137 | +} // namespace details; | |
138 | + | |
139 | +inline namespace cpp2020 | |
140 | +{ | |
141 | + | |
142 | +#if YB_Impl_Chrono_has_cpp20_chrono_is_clock | |
143 | +using std::chrono::is_clock; | |
144 | +#else | |
145 | +//! \ingroup YBase_replacement_features unary_type_traits | |
146 | +template<typename _tClock> | |
147 | +struct is_clock : details::is_clock<_tClock> | |
148 | +{}; | |
149 | +#endif | |
150 | + | |
151 | +#if __cplusplus >= 202002L | |
152 | +using std::chrono::days; | |
153 | +using std::chrono::weeks; | |
154 | +using std::chrono::years; | |
155 | +using std::chrono::months; | |
156 | +#else | |
157 | +// XXX: The representation type is enough here by specification. Use %hours | |
158 | +// because it is just shortest. Ignore any other possibility of using different | |
159 | +// types in ISO C++11 modes onwards (if supported by the implementation). | |
160 | +using days = duration<hours::rep, | |
161 | + std::ratio_multiply<std::ratio<24>, hours::period>>; | |
162 | +using weeks = duration<hours::rep, | |
163 | + std::ratio_multiply<std::ratio<7>, hours::period>>; | |
164 | +using years = duration<hours::rep, | |
165 | + std::ratio_multiply<std::ratio<146097, 400>, hours::period>>; | |
166 | +using months = duration<hours::rep, | |
167 | + std::ratio_divide<years::period, std::ratio<12>>>; | |
168 | +#endif | |
169 | + | |
170 | +#if YB_Impl_Chrono_has_cpp20_chrono_stable | |
171 | +using std::chrono::sys_time; | |
172 | +using std::chrono::sys_seconds; | |
173 | +using std::chrono::sys_days; | |
174 | +#else | |
175 | +//! \ingroup YBase_replacement_features | |
176 | +//!@{ | |
177 | +template<class _tDuration> | |
178 | +using sys_time = time_point<system_clock, _tDuration>; | |
179 | + | |
180 | +using sys_seconds = sys_time<seconds>; | |
181 | + | |
182 | +using sys_days = sys_time<days>; | |
183 | +//!@} | |
184 | +#endif | |
185 | + | |
186 | +#undef YB_Impl_Chrono_has_cpp20_chrono_is_clock | |
187 | +#undef YB_Impl_Chrono_has_cpp20_chrono_stable | |
188 | + | |
189 | +} // inline namespace cpp2020; | |
190 | + | |
191 | +//! \ingroup unary_type_traits | |
192 | +//!@{ | |
193 | +//! \brief 判断指定类型是否是时间间隔。 | |
194 | +template<typename _type> | |
195 | +struct is_duration : is_instance_of<_type, vseq::_a<duration>> | |
196 | +{}; | |
197 | + | |
198 | +//! \brief 判断指定类型是否是时间点。 | |
199 | +template<typename _type> | |
200 | +struct is_time_point : is_instance_of<_type, vseq::_a<time_point>> | |
201 | +{}; | |
202 | +//!@} | |
203 | + | |
204 | +/*! | |
205 | +\ingroup trasformation_traits | |
206 | +\sa enable_if_t | |
207 | +*/ | |
208 | +//!@{ | |
209 | +//! \sa is_duration | |
210 | +template<typename _type> | |
211 | +using enable_if_duration_t = enable_if_t<is_duration<_type>{}, _type>; | |
212 | + | |
213 | +//! \sa is_time_point | |
214 | +template<typename _type> | |
215 | +using enable_if_time_point_t = enable_if_t<is_time_point<_type>{}, _type>; | |
216 | +//!@} | |
217 | + | |
218 | +/*! | |
219 | +\ingroup customization_points unary_type_traits | |
220 | +\brief 指定不需要检查溢出。 | |
221 | +\sa treat_as_floating_point | |
222 | + | |
223 | +指定不视为可溢出而需要检查的表示类型。 | |
224 | +以下类型默认视为不需要检查溢出: | |
225 | + 满足 treat_as_floating_point 的类型。 | |
226 | + 特化 std::numeric_limits 为无界数的类型。 | |
227 | +程序可特化类型改变以上默认行为。 | |
228 | +*/ | |
229 | +template<typename _type> | |
230 | +struct unchecked_rep : details::unchecked_rep<_type> | |
231 | +{}; | |
232 | + | |
233 | + | |
234 | +/*! | |
235 | +\tparam _tTimeSpec 转换的结果类型,和 ISO C++17 std::timespec 兼容。 | |
236 | +\tparam _tRep 时间间隔的表示类型。 | |
237 | +\note 兼容指具有同名的整数类型成员且涵盖表示范围。 | |
238 | +\see WG21 P0972R0 。 | |
239 | +*/ | |
240 | +//!@{ | |
241 | +//! \brief 转换纳秒计数的时间间隔和 ISO C++17 \c std::timespec 兼容的类型的值。 | |
242 | +template<class _tTimeSpec, typename _tRep> | |
243 | +YB_ATTR_nodiscard YB_STATELESS yconstfn_relaxed | |
244 | + enable_if_t<is_timespec_like<_tTimeSpec>{}, _tTimeSpec> | |
245 | +ns_to_timespec(duration<_tRep, std::nano> ns) ynothrow | |
246 | +{ | |
247 | + static_assert(duration_values<_tRep>::max() >= std::nano::den - 1, | |
248 | + "Invalid representation type for nanoseconds found."); | |
249 | + const auto s(duration_cast<duration<_tRep>>(ns)); | |
250 | + _tTimeSpec ts; | |
251 | + using ts_sec_t = decltype(ts.tv_sec); | |
252 | + // XXX: Non-throwing, see $2024-03 %Documentation::Workflow. | |
253 | + const auto ts_sec_max(duration_values<ts_sec_t>::max()); | |
254 | + const auto c(s.count()); | |
255 | + | |
256 | + if(c < ts_sec_max) | |
257 | + yunseq(ts.tv_sec = ts_sec_t(c), | |
258 | + ts.tv_nsec = decltype(ts.tv_nsec)((ns - s).count())); | |
259 | + else | |
260 | + yunseq(ts.tv_sec = ts_sec_max, ts.tv_nsec = std::nano::den - 1); | |
261 | + return ts; | |
262 | +} | |
263 | + | |
264 | +/*! | |
265 | +\brief ISO C++17 \c std::timespec 兼容的类型的值到纳秒计数的时间间隔。 | |
266 | +\pre 断言:纳秒数小于 \c std::nano::den 。 | |
267 | +*/ | |
268 | +template<typename _tRep, class _tTimeSpec> | |
269 | +YB_ATTR_nodiscard YB_STATELESS yconstfn_relaxed | |
270 | + enable_if_t<is_timespec_like<_tTimeSpec>{}, duration<_tRep, std::nano>> | |
271 | +timespec_to_ns(_tTimeSpec ts) | |
272 | +{ | |
273 | + static_assert(duration_values<_tRep>::max() >= std::nano::den - 1, | |
274 | + "Invalid representation type for nanoseconds found."); | |
275 | + using ns_t = duration<_tRep, std::nano>; | |
276 | + | |
277 | + YAssert(ts.tv_nsec < std::nano::den, "Invalid nanoseconds count found."); | |
278 | + return duration_cast<ns_t>(duration<_tRep>(ts.tv_sec)) | |
279 | + + ns_t(ts.tv_nsec); | |
280 | +} | |
281 | +//!@} | |
282 | + | |
283 | + | |
284 | +namespace details | |
285 | +{ | |
286 | + | |
287 | +template<typename _tTo, typename _tFrom, bool = is_unsigned<_tTo>{}> | |
288 | +struct min_rep_check final | |
289 | +{ | |
290 | + static void | |
291 | + check_underflow(const _tFrom& x) | |
292 | + { | |
293 | + if(YB_UNLIKELY(x < duration_values<_tTo>::min())) | |
294 | + throw_underflow_error("Value underflow detected in cast."); | |
295 | + } | |
296 | +}; | |
297 | + | |
298 | +template<typename _tTo, typename _tFrom> | |
299 | +struct min_rep_check<_tTo, _tFrom, true> final | |
300 | +{ | |
301 | + static void | |
302 | + check_underflow(const _tFrom& x) | |
303 | + { | |
304 | + // XXX: Duration representations are required having zero values. More | |
305 | + // general types may be not, and the %_tFrom may be non-integral (but | |
306 | + // an integer-like class). So this is kept here instead | |
307 | + // %CStandardInteger. | |
308 | + if(YB_UNLIKELY(x < duration_values<_tFrom>::zero())) | |
309 | + throw_underflow_error("Value underflow detected in cast."); | |
310 | + } | |
311 | +}; | |
312 | + | |
313 | + | |
314 | +template<typename _tTo, typename _tFrom> | |
315 | +struct max_rep_check final | |
316 | +{ | |
317 | + static void | |
318 | + check_overflow(const _tFrom& x) | |
319 | + { | |
320 | + if(YB_UNLIKELY(x > duration_values<_tTo>::max())) | |
321 | + throw_overflow_error("Value overflow detected in cast."); | |
322 | + } | |
323 | +}; | |
324 | + | |
325 | + | |
326 | +//! \ingroup functors | |
327 | +//!@{ | |
328 | +template<typename _tTo, typename _tFrom, bool, bool> | |
329 | +struct checked_rep_int | |
330 | +{ | |
331 | + YB_ATTR_nodiscard YB_PURE _tTo | |
332 | + operator()(const _tFrom& x) const | |
333 | + { | |
334 | + max_rep_check<_tTo, _tFrom>::check_overflow(x); | |
335 | + min_rep_check<_tTo, _tFrom>::check_underflow(x); | |
336 | + return static_cast<_tTo>(x); | |
337 | + } | |
338 | +}; | |
339 | + | |
340 | +template<typename _tTo, typename _tFrom> | |
341 | +struct checked_rep_int<_tTo, _tFrom, true, false> | |
342 | +{ | |
343 | + YB_ATTR_nodiscard YB_PURE _tTo | |
344 | + operator()(const _tFrom& x) const | |
345 | + { | |
346 | + max_rep_check<_tTo, _tFrom>::check_overflow(x); | |
347 | + return static_cast<_tTo>(x); | |
348 | + } | |
349 | +}; | |
350 | + | |
351 | +template<typename _tTo, typename _tFrom> | |
352 | +struct checked_rep_int<_tTo, _tFrom, false, true> | |
353 | +{ | |
354 | + YB_ATTR_nodiscard YB_PURE _tTo | |
355 | + operator()(const _tFrom& x) const | |
356 | + { | |
357 | + min_rep_check<_tTo, _tFrom>::check_underflow(x); | |
358 | + return static_cast<_tTo>(x); | |
359 | + } | |
360 | +}; | |
361 | + | |
362 | +template<typename _tTo, typename _tFrom> | |
363 | +struct checked_rep_int<_tTo, _tFrom, false, false> | |
364 | +{ | |
365 | + // XXX: Only conversions without exception are supported. | |
366 | + YB_ATTR_nodiscard YB_PURE _tTo | |
367 | + operator()(const _tFrom& x) const ynothrow | |
368 | + { | |
369 | + return static_cast<_tTo>(x); | |
370 | + } | |
371 | +}; | |
372 | +//!@} | |
373 | + | |
374 | +} // namespace details; | |
375 | + | |
376 | +//! \ingroup functors | |
377 | +//!@{ | |
378 | +//! \brief 检查溢出的表示转换函数。 | |
379 | +template<typename _tTo, typename _tFrom, bool = treat_as_floating_point<_tTo>{}> | |
380 | +struct checked_rep_caster | |
381 | +{ | |
382 | + // XXX: Only conversions without exception are supported. | |
383 | + YB_PURE yconstfn _tTo | |
384 | + operator()(const _tFrom& x) const ynothrow | |
385 | + { | |
386 | + return static_cast<_tTo>(x); | |
387 | + } | |
388 | +}; | |
389 | + | |
390 | +template<typename _tTo, typename _tFrom> | |
391 | +struct checked_rep_caster<_tTo, _tFrom, false> | |
392 | + : details::checked_rep_int<_tTo, _tFrom, (std::float_t(duration_values<_tTo> | |
393 | + ::max()) < std::float_t(duration_values<_tFrom>::max())), | |
394 | + (std::float_t(duration_values<_tTo>::min()) | |
395 | + > std::float_t(duration_values<_tFrom>::min()))> | |
396 | +{}; | |
397 | + | |
398 | +template<typename _tTo> | |
399 | +struct checked_rep_caster<_tTo, _tTo, false> | |
400 | +{ | |
401 | + YB_PURE yconstfn _tTo | |
402 | + operator()(const _tTo& x) const ynothrow | |
403 | + { | |
404 | + return x; | |
405 | + } | |
406 | +}; | |
407 | + | |
408 | + | |
409 | +//! \brief 检查上溢的表示转换函数。 | |
410 | +template<typename _tTo, typename _tFrom, bool = treat_as_floating_point<_tTo>{}> | |
411 | +struct checked_max_rep_caster | |
412 | +{ | |
413 | + // XXX: Ditto. | |
414 | + YB_PURE yconstfn _tTo | |
415 | + operator()(const _tFrom& x) const ynothrow | |
416 | + { | |
417 | + return static_cast<_tTo>(x); | |
418 | + } | |
419 | +}; | |
420 | + | |
421 | +template<typename _tTo, typename _tFrom> | |
422 | +struct checked_max_rep_caster<_tTo, _tFrom, false> | |
423 | + : details::checked_rep_int<_tTo, _tFrom, (std::float_t(duration_values<_tTo> | |
424 | + ::max()) < std::float_t(duration_values<_tFrom>::max())), false> | |
425 | +{}; | |
426 | + | |
427 | +template<typename _tTo> | |
428 | +struct checked_max_rep_caster<_tTo, _tTo, false> | |
429 | +{ | |
430 | + YB_PURE yconstfn _tTo | |
431 | + operator()(const _tTo& x) const ynothrow | |
432 | + { | |
433 | + return x; | |
434 | + } | |
435 | +}; | |
436 | + | |
437 | + | |
438 | +//! \brief 检查下溢的表示转换函数。 | |
439 | +template<typename _tTo, typename _tFrom, bool = treat_as_floating_point<_tTo>{}> | |
440 | +struct checked_min_rep_caster | |
441 | +{ | |
442 | + // XXX: Ditto. | |
443 | + YB_PURE yconstfn _tTo | |
444 | + operator()(const _tFrom& x) const ynothrow | |
445 | + { | |
446 | + return static_cast<_tTo>(x); | |
447 | + } | |
448 | +}; | |
449 | + | |
450 | +template<typename _tTo, typename _tFrom> | |
451 | +struct checked_min_rep_caster<_tTo, _tFrom, false> | |
452 | + : details::checked_rep_int<_tTo, _tFrom, false, (std::float_t( | |
453 | + duration_values<_tTo>::min()) | |
454 | + > std::float_t(duration_values<_tFrom>::min()))> | |
455 | +{}; | |
456 | + | |
457 | +template<typename _tTo> | |
458 | +struct checked_min_rep_caster<_tTo, _tTo, false> | |
459 | +{ | |
460 | + YB_PURE yconstfn _tTo | |
461 | + operator()(const _tTo& x) const ynothrow | |
462 | + { | |
463 | + return x; | |
464 | + } | |
465 | +}; | |
466 | +//!@} | |
467 | + | |
468 | + | |
469 | +/*! | |
470 | +\brief 检查溢出的表示转换。 | |
471 | +\tparam _tDst 目标类型。 | |
472 | +\tparam _tSrc 源类型。 | |
473 | +*/ | |
474 | +//!@{ | |
475 | +template<typename _tDst, typename _tSrc, | |
476 | + bool _vAsFloat = treat_as_floating_point<_tDst>{}> | |
477 | +yconstfn _tDst | |
478 | +checked_rep_cast(_tSrc v) | |
479 | +{ | |
480 | + return checked_rep_caster<_tDst, _tSrc, _vAsFloat>()(v); | |
481 | +} | |
482 | + | |
483 | +template<typename _tDst, typename _tSrc, | |
484 | + bool _vAsFloat = treat_as_floating_point<_tDst>{}> | |
485 | +yconstfn _tDst | |
486 | +checked_max_rep_cast(_tSrc v) | |
487 | +{ | |
488 | + return checked_max_rep_caster<_tDst, _tSrc, _vAsFloat>()(v); | |
489 | +} | |
490 | + | |
491 | +template<typename _tDst, typename _tSrc, | |
492 | + bool _vAsFloat = treat_as_floating_point<_tDst>{}> | |
493 | +yconstfn _tDst | |
494 | +checked_min_rep_cast(_tSrc v) | |
495 | +{ | |
496 | + return checked_min_rep_caster<_tDst, _tSrc, _vAsFloat>()(v); | |
497 | +} | |
498 | +//!@} | |
499 | + | |
500 | + | |
501 | +namespace details | |
502 | +{ | |
503 | + | |
504 | +template<typename _tDst, _tDst _vMul, typename _tSrc> | |
505 | +YB_ATTR_nodiscard inline auto | |
506 | +multiply_time(_tSrc x, false_) -> decltype(_vMul * _vMul) | |
507 | +{ | |
508 | + return ystdex::checked_constant_multiply<_tDst, _vMul>( | |
509 | + checked_rep_caster<_tDst, _tSrc, false>()(x)); | |
510 | +} | |
511 | +template<typename _tDst, _tDst _vMul, typename _tSrc> | |
512 | +YB_ATTR_nodiscard YB_STATELESS yconstfn auto | |
513 | +multiply_time(_tSrc x, true_) ynoexcept_spec(_vMul * _vMul) | |
514 | + -> decltype(_vMul * _vMul) | |
515 | +{ | |
516 | + static_assert(or_<is_floating_point<_tDst>, is_class<_tDst>>(), | |
517 | + "Invalid destination representation type found."); | |
518 | + | |
519 | + return _tDst(x) * _vMul; | |
520 | +} | |
521 | + | |
522 | +} // namespace details; | |
523 | + | |
524 | +/*! | |
525 | +\brief 检查参数表示的时间间隔表示值经模板参数指定的时钟转换时的溢出。 | |
526 | +\pre 第一模板参数指定的时钟满足 ISO C++20 Cpp17Clock 要求。 | |
527 | +\pre 第二模板参数指定的时钟的时间间隔是显式特化了 std::numeric_limits 的类型。 | |
528 | +\exception std::overflow 上溢:计算结果大于结果类型可表示的最大值。 | |
529 | +\exception std::overflow 下溢:计算结果小于结果类型可表示的最小值。 | |
530 | +\note 函数参数可以是 \c std::time_t 或无符号整数类型的值。 | |
531 | +*/ | |
532 | +template<typename _tDst, _tDst _vMul, typename _tRep> | |
533 | +yconstfn auto | |
534 | +multiply_time(_tRep t) ynoexcept_spec(details::multiply_time<_tDst, _vMul>(t, | |
535 | + treat_as_floating_point<_tDst>())) -> yimpl(decltype( | |
536 | + details::multiply_time<_tDst, _vMul>(t, unchecked_rep<_tDst>()))) | |
537 | +{ | |
538 | + return details::multiply_time<_tDst, _vMul>(t, unchecked_rep<_tDst>()); | |
539 | +} | |
540 | + | |
541 | +/*! | |
542 | +\brief 检查参数表示的时间间隔表示值经模板参数指定的时钟转换时的溢出。 | |
543 | +\pre 第一模板参数指定的时钟满足 ISO C++20 Cpp17Clock 要求。 | |
544 | +\pre 第二模板参数指定的时钟的时间间隔是显式特化了 std::numeric_limits 的类型。 | |
545 | +\exception std::overflow 上溢。 | |
546 | +\exception std::overflow 下溢。 | |
547 | +\note 函数参数可以是 \c std::time_t 或无符号整数类型的值。 | |
548 | +*/ | |
549 | +template<class _tClock, typename _tRep> | |
550 | +inline auto | |
551 | +multiply_time_on(_tRep t) ynoexcept_spec(chrono::multiply_time< | |
552 | + typename _tClock::rep, _tClock::period::num>(t)) -> yimpl(decltype( | |
553 | + chrono::multiply_time<typename _tClock::rep, _tClock::period::num>(t))) | |
554 | +{ | |
555 | + return | |
556 | + chrono::multiply_time<typename _tClock::rep, _tClock::period::num>(t); | |
557 | +} | |
558 | + | |
559 | +/*! | |
560 | +\note 不使用 common_type_t 以允许另行单独检查转换时可能的溢出。 | |
561 | +\exception std::overflow 上溢:转换的中间计算或结果的不能被最大值表示。 | |
562 | +\exception std::overflow 下溢:转换的中间计算或结果的不能被最小值表示。 | |
563 | +*/ | |
564 | +//!@{ | |
565 | +//! \brief 检查溢出的加法。 | |
566 | +template<typename _tRep, class _tPeriod, | |
567 | + typename = enable_if_t<!is_unbounded_number<_tRep>{}>> | |
568 | +YB_ATTR_nodiscard YB_PURE duration<_tRep, _tPeriod> | |
569 | +checked_plus(const duration<_tRep, _tPeriod>& x, | |
570 | + const duration<_tRep, _tPeriod>& y) | |
571 | +{ | |
572 | + return | |
573 | + duration<_tRep, _tPeriod>(ystdex::checked_plus(x.count(), y.count())); | |
574 | +} | |
575 | + | |
576 | +//! \brief 检查溢出的减法。 | |
577 | +template<typename _tRep, class _tPeriod, | |
578 | + typename = enable_if_t<!is_unbounded_number<_tRep>{}>> | |
579 | +YB_ATTR_nodiscard YB_PURE duration<_tRep, _tPeriod> | |
580 | +checked_minus(const duration<_tRep, _tPeriod>& x, | |
581 | + const duration<_tRep, _tPeriod>& y) | |
582 | +{ | |
583 | + return | |
584 | + duration<_tRep, _tPeriod>(ystdex::checked_minus(x.count(), y.count())); | |
585 | +} | |
586 | +//!@} | |
587 | + | |
588 | +namespace details | |
589 | +{ | |
590 | + | |
591 | +template<class _tTo, class _tFrom> | |
592 | +using conv_cr_t | |
593 | + = common_type_t<typename _tTo::rep, typename _tFrom::rep, intmax_t>; | |
594 | + | |
595 | +//! \ingroup functors | |
596 | +//!@{ | |
597 | +template<class _tTo, class _tFrom, class _tPeriod = typename | |
598 | + std::ratio_divide<typename _tFrom::period, typename _tTo::period>::type, | |
599 | + bool = _tPeriod::num == 1, bool = _tPeriod::den == 1> | |
600 | +struct checked_duration_cast_impl; | |
601 | + | |
602 | +template<class _tTo, class _tFrom, class _tPeriod> | |
603 | +struct checked_duration_cast_impl<_tTo, _tFrom, _tPeriod, true, true> | |
604 | +{ | |
605 | + static_assert(_tPeriod::den > 0, "Invalid period type found."); | |
606 | + static_assert(_tPeriod::num > 0, "Invalid period type found."); | |
607 | + | |
608 | + YB_ATTR_nodiscard YB_PURE yconstfn _tTo | |
609 | + operator()(const _tFrom& d) const | |
610 | + { | |
611 | + return _tTo(checked_rep_caster<typename _tTo::rep, | |
612 | + typename _tFrom::rep>()(d.count())); | |
613 | + } | |
614 | +}; | |
615 | + | |
616 | +template<class _tTo, class _tFrom, class _tPeriod> | |
617 | +struct checked_duration_cast_impl<_tTo, _tFrom, _tPeriod, true, false> | |
618 | +{ | |
619 | + static_assert(_tPeriod::den > 0, "Invalid period type found."); | |
620 | + static_assert(_tPeriod::num > 0, "Invalid period type found."); | |
621 | + | |
622 | + YB_ATTR_nodiscard YB_PURE yconstfn _tTo | |
623 | + operator()(const _tFrom& d) const | |
624 | + { | |
625 | + using cr_t = conv_cr_t<_tTo, _tFrom>; | |
626 | + | |
627 | + return _tTo(checked_rep_caster<typename _tTo::rep, typename | |
628 | + _tFrom::rep>() (d.count()) / static_cast<cr_t>(_tPeriod::den)); | |
629 | + } | |
630 | +}; | |
631 | + | |
632 | +template<class _tTo, class _tFrom, class _tPeriod> | |
633 | +struct checked_duration_cast_impl<_tTo, _tFrom, _tPeriod, false, true> | |
634 | +{ | |
635 | + static_assert(_tPeriod::den > 0, "Invalid period type found."); | |
636 | + static_assert(_tPeriod::num > 0, "Invalid period type found."); | |
637 | + | |
638 | + YB_ATTR_nodiscard YB_PURE yconstfn _tTo | |
639 | + operator()(const _tFrom& d) const | |
640 | + { | |
641 | + using cr_t = conv_cr_t<_tTo, _tFrom>; | |
642 | + | |
643 | + return _tTo(chrono::multiply_time<cr_t, static_cast<cr_t>( | |
644 | + _tPeriod::num)>(d.count())); | |
645 | + } | |
646 | +}; | |
647 | + | |
648 | +template<class _tTo, class _tFrom, class _tPeriod> | |
649 | +struct checked_duration_cast_impl<_tTo, _tFrom, _tPeriod, false, false> | |
650 | +{ | |
651 | + static_assert(_tPeriod::den > 0, "Invalid period type found."); | |
652 | + static_assert(_tPeriod::num > 0, "Invalid period type found."); | |
653 | + | |
654 | + YB_ATTR_nodiscard YB_PURE yconstfn _tTo | |
655 | + operator()(const _tFrom& d) const | |
656 | + { | |
657 | + using cr_t = conv_cr_t<_tTo, _tFrom>; | |
658 | + | |
659 | + return _tTo(chrono::multiply_time<cr_t, static_cast<cr_t>( | |
660 | + _tPeriod::num)>(d.count()) / static_cast<cr_t>(_tPeriod::den)); | |
661 | + } | |
662 | +}; | |
663 | + | |
664 | + | |
665 | +template<class _tDst, typename _tRep, class _tPeriod> | |
666 | +struct checked_duration_cast_dispatch | |
667 | + : checked_duration_cast_impl<_tDst, duration<_tRep, _tPeriod>> | |
668 | +{}; | |
669 | + | |
670 | +template<typename _tRep, class _tPeriod> | |
671 | +struct | |
672 | + checked_duration_cast_dispatch<duration<_tRep, _tPeriod>, _tRep, _tPeriod> | |
673 | +{ | |
674 | + YB_ATTR_nodiscard YB_PURE yconstfn duration<_tRep, _tPeriod> | |
675 | + operator()(const duration<_tRep, _tPeriod>& d) const ynothrow | |
676 | + { | |
677 | + return d; | |
678 | + } | |
679 | +}; | |
680 | +//!@} | |
681 | + | |
682 | +//! \ingroup type_traits | |
683 | +template<typename, typename, class, typename = void> | |
684 | +struct duration_cast_spec : true_ | |
685 | +{}; | |
686 | + | |
687 | +#if YB_HAS_NOEXCEPT | |
688 | +template<typename _tDst, typename _tRep, class _tPeriod> | |
689 | +struct duration_cast_spec<_tDst, _tRep, _tPeriod, enable_if_duration_t<_tDst>> | |
690 | + : bool_<noexcept(checked_duration_cast_dispatch<_tDst, _tRep, _tPeriod>()( | |
691 | + std::declval<const _tDst&>()))> | |
692 | +{}; | |
693 | +#endif | |
694 | + | |
695 | +} // unnamed namespace; | |
696 | + | |
697 | +/*! | |
698 | +\exception std::overflow 上溢:转换的中间计算或结果的不能被最大值表示。 | |
699 | +\exception std::overflow 下溢:转换的中间计算或结果的不能被最小值表示。 | |
700 | +\sa duration_cast | |
701 | +\sa uncheced_rep | |
702 | +*/ | |
703 | +//!@{ | |
704 | +/*! | |
705 | +\brief 带有溢出检查的时间间隔转换。 | |
706 | + | |
707 | +同 duration_cast ,但对不满足 unchecked_rep 的表示类型检查算术操作, | |
708 | + 以避免整数溢出。 | |
709 | +和 std::chrono::duration_cast 不同, | |
710 | + 结果转换为低精度时截断值而不一定具有实现相同的定义舍入行为。 | |
711 | +*/ | |
712 | +template<class _tDst, typename _tRep, class _tPeriod> | |
713 | +YB_ATTR_nodiscard yconstfn_relaxed enable_if_duration_t<_tDst> | |
714 | +checked_duration_cast(const duration<_tRep, _tPeriod>& d) ynoexcept( | |
715 | + details::duration_cast_spec<_tDst, _tRep, _tPeriod>()) | |
716 | +{ | |
717 | + return details::checked_duration_cast_dispatch<_tDst, _tRep, _tPeriod>()(d); | |
718 | +} | |
719 | + | |
720 | +/*! | |
721 | +\brief 带有溢出检查的时间点转换。 | |
722 | + | |
723 | +同 time_point_cast ,但使用 chrono::checked_duration_cast 检查,以避免整数溢出。 | |
724 | +*/ | |
725 | +template<class _tDst, class _tClock, class _tDuration> | |
726 | +YB_ATTR_nodiscard yconstfn_relaxed | |
727 | + enable_if_t<is_duration<_tDst>{}, time_point<_tClock, _tDst>> | |
728 | +checked_time_point_cast(const time_point<_tClock, _tDuration>& t) | |
729 | + ynoexcept(details::duration_cast_spec<_tDst, typename _tClock::rep, | |
730 | + typename _tClock::period>()) | |
731 | +{ | |
732 | + return time_point<_tClock, _tDst>( | |
733 | + chrono::checked_duration_cast<_tDst>(t.time_since_epoch())); | |
734 | +} | |
735 | +//!@} | |
736 | + | |
737 | +} // namespace chrono; | |
738 | + | |
739 | +} // namespace ystdex; | |
740 | + | |
741 | +#endif | |
742 | + |
@@ -1,5 +1,5 @@ | ||
1 | 1 | /* |
2 | - © 2012-2013, 2015-2016, 2018-2023 FrankHB. | |
2 | + © 2012-2013, 2015-2016, 2018-2024 FrankHB. | |
3 | 3 | |
4 | 4 | This file is part of the YSLib project, and may only be used, modified, |
5 | 5 | and distributed under the terms of the YSLib project license. |
@@ -10,13 +10,13 @@ | ||
10 | 10 | /*! \file cstdint.hpp |
11 | 11 | \ingroup YStandardEx |
12 | 12 | \brief ISO C 标准整数类型和相关扩展操作。 |
13 | -\version r941 | |
13 | +\version r1160 | |
14 | 14 | \author FrankHB <frankhb1989@gmail.com> |
15 | 15 | \since build 245 |
16 | 16 | \par 创建时间: |
17 | 17 | 2013-08-24 20:28:18 +0800 |
18 | 18 | \par 修改时间: |
19 | - 2023-12-17 00:10 +0800 | |
19 | + 2024-04-14 22:20 +0800 | |
20 | 20 | \par 文本编码: |
21 | 21 | UTF-8 |
22 | 22 | \par 模块名称: |
@@ -27,24 +27,60 @@ | ||
27 | 27 | #ifndef YB_INC_ystdex_cstdint_hpp_ |
28 | 28 | #define YB_INC_ystdex_cstdint_hpp_ 1 |
29 | 29 | |
30 | -#include "iterator_op.hpp" // for <cstdint>, CHAR_BIT, size_t_, make_signed, | |
31 | -// make_unsigned, size_t, std::uint_fast8_t, std::int64_t, std::uint64_t, | |
32 | -// is_signed, _t, common_type, cond_t, and_, is_unsigned, bool_, | |
33 | -// std::uintmax_t, yconstraint, YB_VerifyIterator, | |
34 | -// ystdex::make_reverse_iterator; | |
35 | -#include <limits> // for std::numeric_limits; | |
36 | -#include <numeric> // for std::accumulate; | |
30 | +#include "iterator_op.hpp" // for <cstdint>, YB_Use_int128, is_same, int128_t, | |
31 | +// uint128_t, std::intmax_t, std::uintmax_t, bool_, cond_t, size_t_, | |
32 | +// bit_width_t, make_signed, make_unsigned, size_t, std::uint_fast8_t, | |
33 | +// std::int64_t, std::uint64_t, is_signed, _t, common_type, and_, is_unsigned, | |
34 | +// or_; | |
35 | +#include "limits.hpp" // for internal "limits.hpp" (implying | |
36 | +// <libdefect/limits.hpp>), is_bounded_binary_integer, | |
37 | +// std::numeric_limits (with fixes); | |
37 | 38 | |
38 | 39 | namespace ystdex |
39 | 40 | { |
40 | 41 | |
41 | 42 | /*! |
43 | +\brief 实现可能支持的最大整数类型。 | |
44 | +\see https://thephd.dev/intmax_t-hell-c++-c 。 | |
45 | +\see https://gcc.gnu.org/pipermail/libstdc++/2020-August/050792.html 。 | |
46 | +\see https://quuxplusone.github.io/blog/2019/02/28/is-int128-integral/ 。 | |
47 | +\since build 983 | |
48 | + | |
49 | +实现支持的最大整数类型可能是非标准扩展整数类型。因为实现限制,此时这些整数不是 | |
50 | + \c std::intmax_t 和 \c std::uintmax_t 。 | |
51 | +为解决这个问题,扩展整数类型在一些实现中不被支持为整数类型,如 libstdc++ 的标准模式。 | |
52 | +但是这种情形不能利用非标准库接口。在此提供有限的变通。 | |
53 | +在所有实现中: | |
54 | + intmax_t 至少具有 \c std::intmax_t 相同的位宽。 | |
55 | + uintmax_t 至少具有 \c std::intmaix_t 相同的位宽。 | |
56 | +*/ | |
57 | +//!@{ | |
58 | +#if YB_Use_int128 > 0 && YB_Use_int128 < 3 | |
59 | +static_assert(!is_same<long long, int128_t>(), "Invalid implementation found."); | |
60 | +static_assert(!is_same<unsigned long long, uint128_t>(), | |
61 | + "Invalid implementation found."); | |
62 | +using intmax_t = int128_t; | |
63 | +using uintmax_t = uint128_t; | |
64 | +#else | |
65 | +using intmax_t = std::intmax_t; | |
66 | +using uintmax_t = std::uintmax_t; | |
67 | +#endif | |
68 | +//!@} | |
69 | + | |
70 | + | |
71 | +/*! | |
42 | 72 | \ingroup unary_type_traits |
43 | -\brief 取指定整数类型的位宽度。 | |
73 | +\brief 取指定整数类型的值表示的位宽度。 | |
74 | +\pre 参数是完整的表示整数的对象类型。 | |
75 | +\pre 参数类型具有 \c std::numeric_limits 特化或值表示和对象表示一致。 | |
44 | 76 | \since build 260 |
45 | 77 | */ |
46 | -template<typename _tInt> | |
47 | -struct integer_width : size_t_<sizeof(_tInt) * CHAR_BIT> | |
78 | +template<typename _type> | |
79 | +// NOTE: Padding bits can be supported when the underlying standard library | |
80 | +// implementation is conforming. See $2019-08 @ %Documentation::Workflow. | |
81 | +struct integer_width : cond_t<is_bounded_binary_integer<_type>, | |
82 | + size_t_<std::numeric_limits<_type>::digits | |
83 | + + (std::numeric_limits<_type>::is_signed ? 1 : 0)>, bit_width_t<_type>> | |
48 | 84 | {}; |
49 | 85 | |
50 | 86 |
@@ -64,6 +100,33 @@ | ||
64 | 100 | //!@} |
65 | 101 | |
66 | 102 | |
103 | +//! \since build 983 | |
104 | +//!@{ | |
105 | +/*! | |
106 | +\brief 提升确切位宽标准整数类型的连续支持的位宽值。 | |
107 | +*/ | |
108 | +YB_ATTR_nodiscard yconstfn size_t | |
109 | +promote_std_integer_width(size_t w) ynothrow | |
110 | +{ | |
111 | + return w <= 8 ? 8 : (w <= 16 ? 16 : (w <= 32 ? 32 : 64)); | |
112 | +} | |
113 | + | |
114 | +/*! | |
115 | +\brief 提升确切位宽整数类型的连续支持的位宽值。 | |
116 | +\since build 983 | |
117 | +*/ | |
118 | +YB_ATTR_nodiscard yconstfn size_t | |
119 | +promote_integer_width(size_t w) ynothrow | |
120 | +{ | |
121 | +#if YB_Use_int128 > 0 | |
122 | + return w <= 64 ? promote_std_integer_width(w) : 128; | |
123 | +#else | |
124 | + return promote_std_integer_width(w); | |
125 | +#endif | |
126 | +} | |
127 | +//!@} | |
128 | + | |
129 | + | |
67 | 130 | /*! |
68 | 131 | \ingroup meta_operations |
69 | 132 | \brief 取按指定宽度的整数类型。 |
@@ -72,20 +135,11 @@ | ||
72 | 135 | */ |
73 | 136 | //!@{ |
74 | 137 | template<size_t _vWidth> |
75 | -struct make_width_int | |
138 | +// XXX: Using a function call in the template argument is friendly to | |
139 | +// IntelliSense int Visual Studio Code (at least with vscode-cpptools v1.19.9). | |
140 | +struct make_width_int : make_width_int<ystdex::promote_integer_width(_vWidth)> | |
76 | 141 | { |
77 | - static_assert(_vWidth <= 64, "Width too large found."); | |
78 | - | |
79 | - using fast_type = typename make_width_int<(_vWidth <= 8U ? 8U | |
80 | - : (_vWidth <= 16U ? 16U : (_vWidth <= 32U ? 32U : 64U)))>::fast_type; | |
81 | - using unsigned_fast_type = typename make_width_int<(_vWidth <= 8U ? 8U | |
82 | - : (_vWidth <= 16U ? 16U : (_vWidth <= 32U ? 32U : 64U)))> | |
83 | - ::unsigned_fast_type; | |
84 | - using least_type = typename make_width_int<(_vWidth <= 8U ? 8U | |
85 | - : (_vWidth <= 16U ? 16U : (_vWidth <= 32U ? 32U : 64U)))>::least_type; | |
86 | - using unsigned_least_type = typename make_width_int<(_vWidth <= 8U ? 8U | |
87 | - : (_vWidth <= 16U ? 16U : (_vWidth <= 32U ? 32U : 64U)))> | |
88 | - ::unsigned_least_type; | |
142 | + static_assert(_vWidth <= YB_MaxIntBits, "Width too large found."); | |
89 | 143 | }; |
90 | 144 | |
91 | 145 | template<> |
@@ -131,6 +185,22 @@ | ||
131 | 185 | using least_type = std::int_least64_t; |
132 | 186 | using unsigned_least_type = std::uint_least64_t; |
133 | 187 | }; |
188 | + | |
189 | +#if YB_Use_int128 > 0 | |
190 | +//! \since build 983 | |
191 | +template<> | |
192 | +struct make_width_int<128U> | |
193 | +{ | |
194 | + using type = int128_t; | |
195 | + using unsigned_type = uint128_t; | |
196 | + // XXX: The following are heuristics without further information specific to | |
197 | + // the concrete implementation. | |
198 | + using fast_type = int128_t; | |
199 | + using unsigned_fast_type = uint128_t; | |
200 | + using least_type = int128_t; | |
201 | + using unsigned_least_type = uint128_t; | |
202 | +}; | |
203 | +#endif | |
134 | 204 | //!@} |
135 | 205 | |
136 | 206 |
@@ -140,8 +210,8 @@ | ||
140 | 210 | \brief 位加倍扩展。 |
141 | 211 | \since build 587 |
142 | 212 | \note 可用于定点数乘除法中间类型。 |
143 | -\todo 使用扩展整数类型保持 64 位类型精度。 | |
144 | 213 | */ |
214 | +//!@{ | |
145 | 215 | template<typename _type, bool _bSigned = is_signed<_type>{}> |
146 | 216 | struct make_widen_int |
147 | 217 | { |
@@ -150,9 +220,34 @@ | ||
150 | 220 | |
151 | 221 | public: |
152 | 222 | using type = _t<make_signed_c<_t<make_width_int< |
153 | - (width() << 1) <= 64 ? width() << 1 : width()>>, _bSigned>>; | |
223 | + (width() << 1) <= YB_MaxIntBits ? width() << 1 : width()>>, _bSigned>>; | |
154 | 224 | }; |
155 | 225 | |
226 | +//! \since build 983 | |
227 | +//!@{ | |
228 | +template<typename _type, bool _bSigned = is_signed<_type>{}> | |
229 | +using make_widen_int_t = _t<make_widen_int<_type, _bSigned>>; | |
230 | + | |
231 | +template<typename _type, bool _bSigned> | |
232 | +struct make_widen_int<const _type, _bSigned> | |
233 | +{ | |
234 | + using type = const make_widen_int_t<_type, _bSigned>; | |
235 | +}; | |
236 | + | |
237 | +template<typename _type, bool _bSigned> | |
238 | +struct make_widen_int<volatile _type, _bSigned> | |
239 | +{ | |
240 | + using type = volatile make_widen_int_t<_type, _bSigned>; | |
241 | +}; | |
242 | + | |
243 | +template<typename _type, bool _bSigned> | |
244 | +struct make_widen_int<const volatile _type, _bSigned> | |
245 | +{ | |
246 | + using type = const volatile make_widen_int_t<_type, _bSigned>; | |
247 | +}; | |
248 | +//!@} | |
249 | +//!@} | |
250 | + | |
156 | 251 | |
157 | 252 | /*! |
158 | 253 | \brief 公共整数类型。 |
@@ -165,6 +260,10 @@ | ||
165 | 260 | struct common_int_type : common_type<_types...> |
166 | 261 | {}; |
167 | 262 | |
263 | +//! \since build 983 | |
264 | +template<typename... _types> | |
265 | +using common_int_type_t = _t<common_int_type<_types...>>; | |
266 | + | |
168 | 267 | template<typename _type1, typename _type2, typename... _types> |
169 | 268 | struct common_int_type<_type1, _type2, _types...> |
170 | 269 | { |
@@ -174,7 +273,7 @@ | ||
174 | 273 | public: |
175 | 274 | using type = typename common_int_type<cond_t< |
176 | 275 | and_<is_unsigned<common_t>, or_<is_signed<_type1>, is_signed<_type2>>>, |
177 | - _t<make_widen_int<common_t, true>>, common_t>, _types...>::type; | |
276 | + make_widen_int_t<common_t, true>, common_t>, _types...>::type; | |
178 | 277 | }; |
179 | 278 | //!@} |
180 | 279 | //!@} |
@@ -182,16 +281,16 @@ | ||
182 | 281 | |
183 | 282 | /*! |
184 | 283 | \ingroup metafunctions |
185 | -\brief 模算术特性:取得不超过模值的最大值。 | |
284 | +\brief 模算术特征:取得不超过模值的最大值。 | |
186 | 285 | \note 不保证值是整数,因此不从 std::integral_constant 派生。 |
187 | 286 | \note 模值 0 表示模为平凡值 1 或不支持模算术。 |
188 | -\note 正确性由用户保证。一般应至少保证 + 和 * 以及相关赋值操作满足模算术语义。 | |
287 | +\note 正确性由程序保证。一般应至少保证 + 和 * 以及相关赋值操作满足模算术语义。 | |
189 | 288 | \since build 440 |
190 | 289 | */ |
191 | 290 | template<typename _type> |
192 | 291 | struct modular_arithmetic |
193 | 292 | { |
194 | - static yconstexpr const _type value = is_unsigned<_type>() | |
293 | + static yconstexpr const _type value = std::numeric_limits<_type>::is_modulo | |
195 | 294 | ? std::numeric_limits<_type>::max() : _type(0); |
196 | 295 | }; |
197 | 296 |
@@ -202,114 +301,10 @@ | ||
202 | 301 | \since build 440 |
203 | 302 | */ |
204 | 303 | template<typename _type1, typename _type2> |
205 | -struct have_same_modulo : bool_<std::uintmax_t(modular_arithmetic< | |
206 | - _type1>()) != 0 && std::uintmax_t(modular_arithmetic<_type1>()) | |
207 | - == std::uintmax_t(modular_arithmetic<_type2>())> | |
304 | +struct have_same_modulo : bool_<modular_arithmetic<_type1>() != 0 | |
305 | + && modular_arithmetic<_type1>() == modular_arithmetic<_type2>()> | |
208 | 306 | {}; |
209 | 307 | |
210 | - | |
211 | -//! \pre 静态断言:整数宽度非零且为 byte 类型宽度的整数倍。 | |
212 | -//!@{ | |
213 | -/*! | |
214 | -\brief 使用迭代器对指定的范围中的字节表示的序列构造无符号整数。 | |
215 | -\pre 范围中的迭代器可解引用。 | |
216 | -\since build 603 | |
217 | -*/ | |
218 | -template<size_t _vWidth, typename _tIn> | |
219 | -YB_ATTR_nodiscard YB_PURE typename make_width_int<_vWidth>::unsigned_type | |
220 | -pack_uint(_tIn first, _tIn last) ynothrowv | |
221 | -{ | |
222 | - static_assert(_vWidth != 0 && _vWidth | |
223 | - % std::numeric_limits<unsigned char>::digits == 0, | |
224 | - "Invalid integer width found."); | |
225 | - using utype = typename make_width_int<_vWidth>::unsigned_type; | |
226 | - | |
227 | - YB_VerifyIterator(first); | |
228 | - return std::accumulate(first, last, utype(), [](utype x, byte y){ | |
229 | - return utype(x << std::numeric_limits<unsigned char>::digits | |
230 | - | utype(y)); | |
231 | - }); | |
232 | -} | |
233 | - | |
234 | -/*! | |
235 | -\brief 分解无符号整数到迭代器对指定的字节范围。 | |
236 | -\pre 断言:范围中的迭代器可解引用。 | |
237 | -\since build 604 | |
238 | -*/ | |
239 | -template<size_t _vWidth, typename _tOut> | |
240 | -void | |
241 | -unpack_uint(typename ystdex::make_width_int<_vWidth>::unsigned_type value, | |
242 | - _tOut result) ynothrow | |
243 | -{ | |
244 | - static_assert(_vWidth != 0 && _vWidth % std::numeric_limits< | |
245 | - unsigned char>::digits == 0, "Invalid integer width found."); | |
246 | - auto n(_vWidth); | |
247 | - | |
248 | - while(!(_vWidth < (n -= std::numeric_limits<unsigned char>::digits))) | |
249 | - { | |
250 | - YB_VerifyIterator(result); | |
251 | - *result = byte(value >> n); | |
252 | - ++result; | |
253 | - } | |
254 | -} | |
255 | -//!@} | |
256 | - | |
257 | -//! \pre 指针参数非空。 | |
258 | -//!@{ | |
259 | -/*! | |
260 | -\brief 从字节缓冲区读取指定宽的大端序无符号整数。 | |
261 | -\since build 623 | |
262 | -*/ | |
263 | -template<size_t _vWidth> | |
264 | -YB_ATTR_nodiscard YB_NONNULL(1) YB_PURE inline | |
265 | - typename make_width_int<_vWidth>::unsigned_type | |
266 | -read_uint_be(const byte* buf) ynothrowv | |
267 | -{ | |
268 | - yconstraint(buf); | |
269 | - return ystdex::pack_uint<_vWidth>(buf, | |
270 | - buf + _vWidth / std::numeric_limits<unsigned char>::digits); | |
271 | -} | |
272 | - | |
273 | -//! \since build 608 | |
274 | -//!@{ | |
275 | -//! \brief 从字节缓冲区读取指定宽的小端序无符号整数。 | |
276 | -template<size_t _vWidth> | |
277 | -YB_ATTR_nodiscard YB_NONNULL(1) YB_PURE inline | |
278 | - typename make_width_int<_vWidth>::unsigned_type | |
279 | -read_uint_le(const byte* buf) ynothrowv | |
280 | -{ | |
281 | - yconstraint(buf); | |
282 | - return ystdex::pack_uint<_vWidth>(ystdex::make_reverse_iterator( | |
283 | - buf + _vWidth / std::numeric_limits<unsigned char>::digits), | |
284 | - ystdex::make_reverse_iterator(buf)); | |
285 | -} | |
286 | - | |
287 | -/*! | |
288 | -\brief 向字节缓冲区写入指定宽的大端序无符号整数。 | |
289 | -\since build 623 | |
290 | -*/ | |
291 | -template<size_t _vWidth> | |
292 | -YB_NONNULL(1) inline void | |
293 | -write_uint_be(byte* buf, typename make_width_int<_vWidth>::unsigned_type val) | |
294 | - ynothrowv | |
295 | -{ | |
296 | - yconstraint(buf); | |
297 | - ystdex::unpack_uint<_vWidth>(val, buf); | |
298 | -} | |
299 | - | |
300 | -//! \brief 向字节缓冲区写入指定宽的小端序无符号整数。 | |
301 | -template<size_t _vWidth> | |
302 | -YB_NONNULL(1) inline void | |
303 | -write_uint_le(byte* buf, typename make_width_int<_vWidth>::unsigned_type val) | |
304 | - ynothrowv | |
305 | -{ | |
306 | - yconstraint(buf); | |
307 | - ystdex::unpack_uint<_vWidth>(val, ystdex::make_reverse_iterator(buf | |
308 | - + _vWidth / std::numeric_limits<unsigned char>::digits)); | |
309 | -} | |
310 | -//!@} | |
311 | -//!@} | |
312 | - | |
313 | 308 | } // namespace ystdex; |
314 | 309 | |
315 | 310 | #endif |
@@ -1,23 +1,22 @@ | ||
1 | 1 | /* |
2 | - © 2016 FrankHB. | |
2 | + © 2016, 2024 FrankHB. | |
3 | 3 | |
4 | - This file is part of the YSLib project, and may only be used, | |
5 | - modified, and distributed under the terms of the YSLib project | |
6 | - license, LICENSE.TXT. By continuing to use, modify, or distribute | |
7 | - this file you indicate that you have read the license and | |
8 | - understand and accept it fully. | |
4 | + This file is part of the YSLib project, and may only be used, modified, | |
5 | + and distributed under the terms of the YSLib project license. | |
6 | + By continuing to use, modify, or distribute this file you indicate that | |
7 | + you have read the license and understand and accept it fully. | |
9 | 8 | */ |
10 | 9 | |
11 | 10 | /*! \file ctime.h |
12 | 11 | \ingroup YStandardEx |
13 | 12 | \brief ISO C 日期和时间接口扩展。 |
14 | -\version r57 | |
13 | +\version r98 | |
15 | 14 | \author FrankHB <frankhb1989@gmail.com> |
16 | 15 | \since build 513 |
17 | 16 | \par 创建时间: |
18 | 17 | 2016-06-23 09:48:32 +0800 |
19 | 18 | \par 修改时间: |
20 | - 2015-06-23 09:52 +0800 | |
19 | + 2024-04-06 15:26 +0800 | |
21 | 20 | \par 文本编码: |
22 | 21 | UTF-8 |
23 | 22 | \par 模块名称: |
@@ -28,14 +27,16 @@ | ||
28 | 27 | #ifndef YB_INC_ystdex_ctime_h_ |
29 | 28 | #define YB_INC_ystdex_ctime_h_ 1 |
30 | 29 | |
31 | -#include "../ydef.h" // for yconstfn; | |
32 | -#include <ctime> // for std::tm; | |
30 | +#include "meta.hpp" // for yconstfn, false_, void_t, enable_if, is_trivial, | |
31 | +// is_arithmetic, is_integral, true_; | |
32 | +#include <ctime> // for <ctime>, std::tm; | |
33 | +#include <libdefect/limits.hpp> // for std::numeric_limits (with fixes); | |
33 | 34 | |
34 | 35 | namespace ystdex |
35 | 36 | { |
36 | 37 | |
37 | 38 | //! \since build 704 |
38 | -//@{ | |
39 | +//!@{ | |
39 | 40 | //! \brief 判断 std::tm 的日期数据成员范围是否有效。 |
40 | 41 | yconstfn bool |
41 | 42 | is_date_range_valid(const std::tm& t) |
@@ -50,7 +51,43 @@ | ||
50 | 51 | return !(t.tm_hour < 0 || 23 < t.tm_hour || t.tm_hour < 0 || 59 < t.tm_min |
51 | 52 | || t.tm_sec < 0 || 59 < t.tm_min); |
52 | 53 | } |
53 | -//@} | |
54 | +//!@} | |
55 | + | |
56 | + | |
57 | +//! \since build 983 | |
58 | +namespace details | |
59 | +{ | |
60 | + | |
61 | +template<typename _type, typename = void> | |
62 | +struct is_timespec_like : false_ | |
63 | +{}; | |
64 | + | |
65 | +template<typename _type> | |
66 | +struct is_timespec_like<_type, void_t<enable_if<is_trivial<_type>{}>, | |
67 | + is_arithmetic<decltype(_type().tv_sec)>, is_integral<decltype(_type() | |
68 | + .tv_nsec)>, enable_if<(std::numeric_limits<decltype(_type().tv_sec)>::max() | |
69 | + > 0)>, enable_if<(std::numeric_limits<decltype(_type().tv_nsec)>::max() | |
70 | + >= 999999999LL)>>> : true_ | |
71 | +{}; | |
72 | + | |
73 | +} // unnamed namespace details; | |
74 | + | |
75 | +/*! | |
76 | +\ingroup unary_type_traits | |
77 | +\brief 判断指定类型是否是类似 ISO C++17 \c std::timespec 的类型。 | |
78 | +\since build 983 | |
79 | + | |
80 | +判断模板参数指定的类型是否类似 ISO C++17 \c std::timespec 类型,即满足以下要求: | |
81 | + 是平凡类型。 | |
82 | + 具有算术类型非静态数据成员 \c tv_sec ,最大值不小于 0 。 | |
83 | + 具有整数类型非静态数据成员 \c tv_nsec ,最大值不小于 999999999 。 | |
84 | +仅要求默认构造,不限制布局和 | |
85 | +不限制 \c tv_sec 的具体类型,以同时兼容不同实现的 \c std::time_t 。 | |
86 | +不限制 \c tv_nsec 的具体类型,以兼容 ISO C23 的 \c ::timespec 。 | |
87 | +*/ | |
88 | +template<typename _type> | |
89 | +struct is_timespec_like : details::is_timespec_like<_type> | |
90 | +{}; | |
54 | 91 | |
55 | 92 | } // namespace ystdex; |
56 | 93 |
@@ -1,5 +1,5 @@ | ||
1 | 1 | /* |
2 | - © 2014-2018, 2020-2023 FrankHB. | |
2 | + © 2014-2018, 2020-2024 FrankHB. | |
3 | 3 | |
4 | 4 | This file is part of the YSLib project, and may only be used, modified, |
5 | 5 | and distributed under the terms of the YSLib project license. |
@@ -10,13 +10,13 @@ | ||
10 | 10 | /*! \file exception.h |
11 | 11 | \ingroup YStandardEx |
12 | 12 | \brief 标准库异常扩展接口。 |
13 | -\version r357 | |
13 | +\version r373 | |
14 | 14 | \author FrankHB <frankhb1989@gmail.com> |
15 | 15 | \since build 522 |
16 | 16 | \par 创建时间: |
17 | 17 | 2014-07-25 20:14:51 +0800 |
18 | 18 | \par 修改时间: |
19 | - 2023-12-20 20:32 +0800 | |
19 | + 2024-04-12 23:30 +0800 | |
20 | 20 | \par 文本编码: |
21 | 21 | UTF-8 |
22 | 22 | \par 模块名称: |
@@ -232,6 +232,24 @@ | ||
232 | 232 | //!@} |
233 | 233 | |
234 | 234 | |
235 | +//! \since build 983 | |
236 | +//!@{ | |
237 | +/*! | |
238 | +\brief 抛出参数指定消息的 \c std::overflow_error 异常。 | |
239 | +\throw std::overflow_error | |
240 | +*/ | |
241 | +YB_NORETURN YB_API YB_NONNULL(1) void | |
242 | +throw_overflow_error(const char* = "Value overflow detected."); | |
243 | + | |
244 | +/*! | |
245 | +\brief 抛出参数指定消息的 \c std::underflow_error 异常。 | |
246 | +\throw std::underflow_error | |
247 | +*/ | |
248 | +YB_NORETURN YB_API YB_NONNULL(1) void | |
249 | +throw_underflow_error(const char* = "Value underflow detected."); | |
250 | +//!@} | |
251 | + | |
252 | + | |
235 | 253 | /*! |
236 | 254 | \brief 抛出错误:\c std::system_error 或允许相同构造函数参数的异常。 |
237 | 255 | \throw _type 使用参数构造的异常。 |
@@ -1,5 +1,5 @@ | ||
1 | 1 | /* |
2 | - © 2011-2023 FrankHB. | |
2 | + © 2011-2024 FrankHB. | |
3 | 3 | |
4 | 4 | This file is part of the YSLib project, and may only be used, modified, |
5 | 5 | and distributed under the terms of the YSLib project license. |
@@ -10,13 +10,13 @@ | ||
10 | 10 | /*! \file iterator.hpp |
11 | 11 | \ingroup YStandardEx |
12 | 12 | \brief 通用迭代器。 |
13 | -\version r6283 | |
13 | +\version r6367 | |
14 | 14 | \author FrankHB <frankhb1989@gmail.com> |
15 | 15 | \since 早于 build 189 |
16 | 16 | \par 创建时间: |
17 | 17 | 2011-01-27 23:01:00 +0800 |
18 | 18 | \par 修改时间: |
19 | - 2023-07-06 21:58 +0800 | |
19 | + 2024-04-17 02:28 +0800 | |
20 | 20 | \par 文本编码: |
21 | 21 | UTF-8 |
22 | 22 | \par 模块名称: |
@@ -29,9 +29,10 @@ | ||
29 | 29 | |
30 | 30 | #include "pointer.hpp" // for "iterator_op.hpp", iterator_operators_t, |
31 | 31 | // std::iterator_traits, is_bitwise_swappable, _t, pointer_classify, cond_t, |
32 | -// exclude_self_t, enable_if_convertible_t, and_, std::input_iterator_tag, | |
33 | -// ystdex::swap_dependent, YB_VerifyIterator, is_undereferenceable, yassume, | |
34 | -// yconstraint, random_access_iteratable; | |
32 | +// void_t, decrement_t, exclude_self_t, enable_if_convertible_t, and_, | |
33 | +// plus_assignment_t, minus_assignment_t, less_t, minus_t, | |
34 | +// std::input_iterator_tag, ystdex::swap_dependent, YB_VerifyIterator, | |
35 | +// is_undereferenceable, yassume, yconstraint, random_access_iteratable; | |
35 | 36 | #include "type_op.hpp" // for first_tag, second_tag; |
36 | 37 | #include <tuple> // for std::tuple, std::get, std::tuple_size; |
37 | 38 | #include "integer_sequence.hpp" // for make_index_sequence, index_sequence; |
@@ -181,24 +182,33 @@ | ||
181 | 182 | using value_type = remove_reference_t<reference>; |
182 | 183 | /*! |
183 | 184 | \since build 667 |
184 | - \todo 测试 operator-> 并支持代理指针。 | |
185 | + \todo 测试 \c operator-> 并支持代理指针。 | |
185 | 186 | */ |
186 | 187 | using pointer = value_type*; |
187 | 188 | }; |
188 | 189 | |
190 | +//! \since build 983 | |
191 | +template<typename... _types> | |
192 | +auto | |
193 | +chk_decrement(std::tuple<_types...>) -> void_t<decrement_t<_types&>...>; | |
194 | + | |
189 | 195 | } // namespace details; |
190 | 196 | |
191 | 197 | |
192 | 198 | /*! |
193 | 199 | \ingroup iterator_adaptors |
194 | 200 | \brief 变换迭代器。 |
195 | -\pre 变换器必须满足 DefaultConstructible ,否则不保证可默认构造。 | |
196 | 201 | \note 对返回新值的二元操作复制的转换器基于第一操作数。 |
197 | 202 | \warning 非虚析构。 |
198 | 203 | \since build 532 |
199 | 204 | |
200 | 205 | 使用指定参数转换得到新迭代器的间接操作替代指定原始类型的间接操作的迭代器适配器。 |
206 | +第一模板参数指定被变换原迭代器类型,应为满足迭代器要求的迭代器。 | |
207 | +第二模板参数指定实现变换的变换器类型。 | |
208 | +第三模板参数指定引用类型。 | |
201 | 209 | 被替代的原始类型是迭代器类型,或除间接操作(可以不存在)外符合迭代器要求的类型。 |
210 | +实例满足第一参数对应的迭代器要求, | |
211 | + 仅当第二参数满足 DefaultConstructible 且第三参数是引用。 | |
202 | 212 | */ |
203 | 213 | template<typename _tIter, typename _fTrans, typename _tReference = void> |
204 | 214 | class transformed_iterator : public iterator_operators_t<transformed_iterator< |
@@ -306,7 +316,9 @@ | ||
306 | 316 | transformed_iterator& |
307 | 317 | operator=(transformed_iterator&&) = default; |
308 | 318 | |
309 | - //! \since build 910 | |
319 | + //! \since build 983 | |
320 | + template<yimpl(typename _type = iterator_type, | |
321 | + typename = plus_assignment_t<_type&, difference_type&>)> | |
310 | 322 | transformed_iterator& |
311 | 323 | operator+=(difference_type n) |
312 | 324 | ynoexcept_spec(std::declval<transformed_iterator&>().get() += n) |
@@ -315,7 +327,9 @@ | ||
315 | 327 | return *this; |
316 | 328 | } |
317 | 329 | |
318 | - //! \since build 910 | |
330 | + //! \since build 983 | |
331 | + template<yimpl(typename _type = iterator_type, | |
332 | + typename = minus_assignment_t<_type&, difference_type&>)> | |
319 | 333 | transformed_iterator& |
320 | 334 | operator-=(difference_type n) |
321 | 335 | ynoexcept_spec(std::declval<transformed_iterator&>().get() -= n) |
@@ -341,7 +355,9 @@ | ||
341 | 355 | return *this; |
342 | 356 | } |
343 | 357 | |
344 | - //! \since build 665 | |
358 | + //! \since build 983 | |
359 | + template<yimpl(typename _type = iterator_type, | |
360 | + typename = decrement_t<_type&>)> | |
345 | 361 | transformed_iterator& |
346 | 362 | operator--() |
347 | 363 | { |
@@ -366,14 +382,16 @@ | ||
366 | 382 | return x.get() == y; |
367 | 383 | } |
368 | 384 | |
369 | - template<yimpl(typename = void)> | |
385 | + template<yimpl(typename _type = iterator_type, | |
386 | + typename = less_t<const _type&>)> | |
370 | 387 | friend yconstfn bool |
371 | 388 | operator<(const transformed_iterator& x, const transformed_iterator& y) |
372 | 389 | ynoexcept_spec(bool(x.get() < y.get())) |
373 | 390 | { |
374 | 391 | return bool(x.get() < y.get()); |
375 | 392 | } |
376 | - template<yimpl(typename = void)> | |
393 | + template<yimpl(typename _type = iterator_type, | |
394 | + typename = less_t<const _type&>)> | |
377 | 395 | friend yconstfn bool |
378 | 396 | operator<(const transformed_iterator& x, const iterator_type& y) |
379 | 397 | ynoexcept_spec(bool(x.get() < y)) |
@@ -381,21 +399,24 @@ | ||
381 | 399 | return bool(x.get() < y); |
382 | 400 | } |
383 | 401 | |
384 | - template<yimpl(typename = void)> | |
402 | + template<yimpl(typename _type = iterator_type, | |
403 | + typename = minus_t<const _type&>)> | |
385 | 404 | friend yconstfn difference_type |
386 | 405 | operator-(const transformed_iterator& x, const transformed_iterator& y) |
387 | 406 | ynoexcept_spec(difference_type(x.get() - y.get())) |
388 | 407 | { |
389 | 408 | return difference_type(x.get() - y.get()); |
390 | 409 | } |
391 | - template<yimpl(typename = void)> | |
410 | + template<yimpl(typename _type = iterator_type, | |
411 | + typename = minus_t<const _type&>)> | |
392 | 412 | friend yconstfn difference_type |
393 | 413 | operator-(const transformed_iterator& x, const iterator_type& y) |
394 | 414 | ynoexcept_spec(difference_type(x.get() - y)) |
395 | 415 | { |
396 | 416 | return difference_type(x.get() - y); |
397 | 417 | } |
398 | - template<yimpl(typename = void)> | |
418 | + template<yimpl(typename _type = iterator_type, | |
419 | + typename = minus_t<const _type&>)> | |
399 | 420 | friend yconstfn difference_type |
400 | 421 | operator-(const iterator_type& x, const transformed_iterator& y) |
401 | 422 | ynoexcept_spec(difference_type(x - y.get())) |
@@ -634,11 +655,12 @@ | ||
634 | 655 | \since build 595 |
635 | 656 | |
636 | 657 | 拼接迭代器和其它对象类型对得到的迭代器适配器。 |
658 | +第二参数指定的迭代器特征应被第一参数支持。否则,不保证提供的操作可用而满足对应特征。 | |
637 | 659 | */ |
638 | 660 | template<typename _tIter, class _tTraits = std::iterator_traits<_tIter>, |
639 | 661 | typename... _tSlaves> |
640 | -class tuple_iterator : private std::tuple<_tIter, _tSlaves...>, public | |
641 | - iterator_operators_t<tuple_iterator<_tIter, _tTraits, _tSlaves...>, | |
662 | +class tuple_iterator : private std::tuple<_tIter, _tSlaves...>, | |
663 | + public iterator_operators_t<tuple_iterator<_tIter, _tTraits, _tSlaves...>, | |
642 | 664 | _tTraits> |
643 | 665 | { |
644 | 666 | public: |
@@ -654,6 +676,18 @@ | ||
654 | 676 | private: |
655 | 677 | using seq_type = make_index_sequence<std::tuple_size<base_type>{}>; |
656 | 678 | |
679 | + //! \since build 983 | |
680 | + template<typename... _types> | |
681 | + static auto | |
682 | + chk_plus_assignment(std::tuple<_types...>) | |
683 | + -> void_t<plus_assignment_t<_types&, difference_type>...>; | |
684 | + | |
685 | + //! \since build 983 | |
686 | + template<typename... _types> | |
687 | + static auto | |
688 | + chk_minus_assignment(std::tuple<_types...>) | |
689 | + -> void_t<minus_assignment_t<_types&, difference_type>...>; | |
690 | + | |
657 | 691 | public: |
658 | 692 | yconstfn |
659 | 693 | tuple_iterator() = default; |
@@ -676,6 +710,13 @@ | ||
676 | 710 | tuple_iterator& |
677 | 711 | operator=(tuple_iterator&&) = default; |
678 | 712 | |
713 | + /*! | |
714 | + \note 满足随机访问迭代器要求。 | |
715 | + \since build 984 | |
716 | + */ | |
717 | + //!@{ | |
718 | + template<yimpl(typename _tBase = base_type, | |
719 | + typename = decltype(chk_plus_assignment(std::declval<_tBase>())))> | |
679 | 720 | tuple_iterator& |
680 | 721 | operator+=(difference_type n) ynoexcept_spec( |
681 | 722 | yimpl(std::declval<tuple_iterator&>().add(n, seq_type()))) |
@@ -684,6 +725,8 @@ | ||
684 | 725 | return *this; |
685 | 726 | } |
686 | 727 | |
728 | + template<yimpl(typename _tBase = base_type, | |
729 | + typename = decltype(chk_minus_assignment(std::declval<_tBase>())))> | |
687 | 730 | tuple_iterator& |
688 | 731 | operator-=(difference_type n) ynoexcept_spec( |
689 | 732 | yimpl(std::declval<tuple_iterator&>().subtract(n, seq_type()))) |
@@ -691,8 +734,9 @@ | ||
691 | 734 | subtract(n, seq_type()); |
692 | 735 | return *this; |
693 | 736 | } |
737 | + //!@} | |
694 | 738 | |
695 | - //! \brief 满足输入迭代器要求。 | |
739 | + //! \note 满足输入迭代器要求。 | |
696 | 740 | //!@{ |
697 | 741 | YB_ATTR_nodiscard yconstfn reference |
698 | 742 | operator*() const |
@@ -710,7 +754,12 @@ | ||
710 | 754 | } |
711 | 755 | //!@} |
712 | 756 | |
713 | - //! \brief 满足双向迭代器要求。 | |
757 | + /*! | |
758 | + \note 满足双向迭代器要求。 | |
759 | + \since build 984 | |
760 | + */ | |
761 | + template<yimpl(typename _tBase = base_type, | |
762 | + typename = decltype(details::chk_decrement(std::declval<_tBase>())))> | |
714 | 763 | tuple_iterator& |
715 | 764 | operator--() |
716 | 765 | ynoexcept_spec(yimpl(std::declval<tuple_iterator&>().dec(seq_type()))) |
@@ -726,6 +775,27 @@ | ||
726 | 775 | return x.get() == y.get(); |
727 | 776 | } |
728 | 777 | |
778 | + //! \since build 983 | |
779 | + //!@{ | |
780 | + template<yimpl(typename _type = iterator_type, | |
781 | + typename = less_t<const _type&>)> | |
782 | + friend yconstfn bool | |
783 | + operator<(const tuple_iterator& x, const tuple_iterator& y) | |
784 | + ynoexcept_spec(bool(x.get() < y.get())) | |
785 | + { | |
786 | + return bool(x.get() < y.get()); | |
787 | + } | |
788 | + | |
789 | + template<yimpl(typename _type = iterator_type, | |
790 | + typename = minus_t<const _type&>)> | |
791 | + friend yconstfn difference_type | |
792 | + operator-(const tuple_iterator& x, const tuple_iterator& y) | |
793 | + ynoexcept_spec(difference_type(x.get() - y.get())) | |
794 | + { | |
795 | + return difference_type(x.get() - y.get()); | |
796 | + } | |
797 | + //!@} | |
798 | + | |
729 | 799 | private: |
730 | 800 | template<size_t... _vSeq> |
731 | 801 | void |
@@ -0,0 +1,158 @@ | ||
1 | +/* | |
2 | + © 2024 FrankHB. | |
3 | + | |
4 | + This file is part of the YSLib project, and may only be used, modified, | |
5 | + and distributed under the terms of the YSLib project license. | |
6 | + By continuing to use, modify, or distribute this file you indicate that | |
7 | + you have read the license and understand and accept it fully. | |
8 | +*/ | |
9 | + | |
10 | +/*! \file limits.hpp | |
11 | +\ingroup YStandardEx | |
12 | +\brief 实现限制。 | |
13 | +\version r157 | |
14 | +\author FrankHB <frankhb1989@gmail.com> | |
15 | +\since build 983 | |
16 | +\par 创建时间: | |
17 | + 2024-04-08 02:17:53 +0800 | |
18 | +\par 修改时间: | |
19 | + 2024-04-15 20:41 +0800 | |
20 | +\par 文本编码: | |
21 | + UTF-8 | |
22 | +\par 模块名称: | |
23 | + YStandardEx::Limits | |
24 | +*/ | |
25 | + | |
26 | + | |
27 | +#ifndef YB_INC_ystdex_limits_hpp_ | |
28 | +#define YB_INC_ystdex_limits_hpp_ 1 | |
29 | + | |
30 | +#include <libdefect/limits.hpp> // for <libdefect/limits.hpp>, | |
31 | +// std::numeric_limits (with fixes); | |
32 | +#include "integral_constant.hpp" // for bool_; | |
33 | + | |
34 | +namespace ystdex | |
35 | +{ | |
36 | + | |
37 | +//! \since build 983 | |
38 | +//!@{ | |
39 | +/*! | |
40 | +\ingroup traits | |
41 | +\brief 数值特征。 | |
42 | +*/ | |
43 | +template<class _type> | |
44 | +struct numeric_traits : std::numeric_limits<_type> | |
45 | +{ | |
46 | + using base = std::numeric_limits<_type>; | |
47 | + | |
48 | + //! \brief 判断是否为有界整数。 | |
49 | + static yconstexpr bool is_bounded_integer = base::is_specialized | |
50 | + && base::is_integer && base::is_bounded; | |
51 | + //! \brief 判断是否为二进制有界整数。 | |
52 | + static yconstexpr bool is_bounded_binary_integer | |
53 | + = is_bounded_integer && base::radix == 2; | |
54 | + //! \brief 判断是否为无界数。 | |
55 | + static yconstexpr bool is_unbounded | |
56 | + = base::is_specialized && !base::is_bounded; | |
57 | + //! \brief 判断是否为任意界限的无界数。 | |
58 | +#if YB_IMPL_GNUCPP || YB_IMPL_CLANGPP | |
59 | + YB_Diag_Push | |
60 | + YB_Diag_Ignore(float-equal) | |
61 | +#endif | |
62 | + static yconstexpr bool is_arbitrary_unbounded = is_unbounded | |
63 | + && base::max() == 0 && base::min() == 0; | |
64 | +#if YB_IMPL_GNUCPP || YB_IMPL_CLANGPP | |
65 | + YB_Diag_Pop | |
66 | +#endif | |
67 | + //! \brief 判断是否具有特殊值。 | |
68 | + static yconstexpr bool has_special_value | |
69 | + = base::is_specialized && base::has_infinity && base::has_quiet_NaN; | |
70 | +}; | |
71 | + | |
72 | + | |
73 | +//! \ingroup unary_type_traits | |
74 | +//!@{ | |
75 | +//! \brief 判断指定类型是否为二进制整数类型。 | |
76 | +template<typename _type> | |
77 | +struct is_bounded_integer | |
78 | + : bool_<numeric_traits<_type>::is_bounded_integer> | |
79 | +{}; | |
80 | + | |
81 | +//! \brief 判断指定类型是否为二进制有界整数类型。 | |
82 | +template<typename _type> | |
83 | +struct is_bounded_binary_integer | |
84 | + : bool_<numeric_traits<_type>::is_bounded_binary_integer> | |
85 | +{}; | |
86 | + | |
87 | +//! \brief 判断参数指定的类型是否为无界数值类型。 | |
88 | +template<typename _type> | |
89 | +struct is_unbounded_number : bool_<numeric_traits<_type>::is_unbounded> | |
90 | +{}; | |
91 | + | |
92 | +//! \brief 判断参数指定的类型是否为无界数值类型。 | |
93 | +template<typename _type> | |
94 | +struct is_arbitrary_unbounded_number | |
95 | + : bool_<numeric_traits<_type>::is_arbitrary_unbounded> | |
96 | +{}; | |
97 | + | |
98 | + | |
99 | +//! \brief 判断参数指定的类型是否具有特殊值。 | |
100 | +template<typename _type> | |
101 | +struct has_special_value : bool_<numeric_traits<_type>::has_special_value> | |
102 | +{}; | |
103 | +//!@} | |
104 | +//!@} | |
105 | + | |
106 | + | |
107 | +namespace details | |
108 | +{ | |
109 | + | |
110 | +template<typename _type, typename _type2, typename = void> | |
111 | +struct is_in_subrange_of : is_arbitrary_unbounded_number<_type2> | |
112 | +{}; | |
113 | + | |
114 | +template<typename _type, typename _type2> | |
115 | +struct is_in_subrange_of<_type, _type2, void_t<bool_<(std::numeric_limits<_type> | |
116 | + ::max() <= std::numeric_limits<_type2>::max() && std::numeric_limits<_type> | |
117 | + ::min() >= std::numeric_limits<_type2>::min())>>> | |
118 | + : or_<is_arbitrary_unbounded_number<_type2>, bool_<(std::numeric_limits< | |
119 | + _type>::max() <= std::numeric_limits<_type2>::max() | |
120 | + && std::numeric_limits<_type>::min() | |
121 | + >= std::numeric_limits<_type2>::min())>> | |
122 | +{}; | |
123 | + | |
124 | +} // namespace details; | |
125 | + | |
126 | +/*! | |
127 | +\ingroup unary_type_traits | |
128 | +\brief 判断第一参数指定的类型是否在第二参数指定的类型的范围内。 | |
129 | +\note 判断值域是否被涵盖,不保证第二个参数中存在无法准确表示第一参数类型的值的情形。 | |
130 | +*/ | |
131 | +template<typename _type, typename... _types> | |
132 | +struct is_in_subrange_of : and_<details::is_in_subrange_of<_type, _types>...> | |
133 | +{}; | |
134 | + | |
135 | + | |
136 | +/*! | |
137 | +\ingroup traits | |
138 | +\brief 判断指定类型是否可作为十进制连续数字的表示。 | |
139 | + | |
140 | +作为十进制数字表示的类型是不少于指定十进制位数的无符号整数。 | |
141 | +*/ | |
142 | +template<size_t _vLen, typename _type> | |
143 | +using rep_in_digits10 = bool_<std::numeric_limits<_type>::is_integer | |
144 | + && !std::numeric_limits<_type>::is_signed | |
145 | + && std::numeric_limits<_type>::digits10 >= _vLen>; | |
146 | + | |
147 | +/*! | |
148 | +\ingroup metafunctions | |
149 | +\sa enable_if_t | |
150 | +*/ | |
151 | +template<size_t _vLen, typename _type> | |
152 | +using enable_if_rep_in_digits10 | |
153 | + = enable_if_t<rep_in_digits10<_vLen, _type>{}, _type>; | |
154 | + | |
155 | +} // namespace ystdex; | |
156 | + | |
157 | +#endif | |
158 | + |
@@ -1,23 +1,22 @@ | ||
1 | 1 | /* |
2 | - © 2019-2023 FrankHB. | |
2 | + © 2019-2024 FrankHB. | |
3 | 3 | |
4 | - This file is part of the YSLib project, and may only be used, | |
5 | - modified, and distributed under the terms of the YSLib project | |
6 | - license, LICENSE.TXT. By continuing to use, modify, or distribute | |
7 | - this file you indicate that you have read the license and | |
8 | - understand and accept it fully. | |
4 | + This file is part of the YSLib project, and may only be used, modified, | |
5 | + and distributed under the terms of the YSLib project license. | |
6 | + By continuing to use, modify, or distribute this file you indicate that | |
7 | + you have read the license and understand and accept it fully. | |
9 | 8 | */ |
10 | 9 | |
11 | 10 | /*! \file list.hpp |
12 | 11 | \ingroup YStandardEx |
13 | 12 | \brief 列表容器。 |
14 | -\version r1881 | |
13 | +\version r1891 | |
15 | 14 | \author FrankHB <frankhb1989@gmail.com> |
16 | 15 | \since build 864 |
17 | 16 | \par 创建时间: |
18 | 17 | 2019-08-14 14:48:52 +0800 |
19 | 18 | \par 修改时间: |
20 | - 2023-02-13 05:13 +0800 | |
19 | + 2024-04-06 15:30 +0800 | |
21 | 20 | \par 文本编码: |
22 | 21 | UTF-8 |
23 | 22 | \par 模块名称: |
@@ -48,7 +47,7 @@ | ||
48 | 47 | // less; |
49 | 48 | #include "compressed_pair.hpp" // for compressed_base; |
50 | 49 | #include "base.h" // for noncopyable, nonmovable; |
51 | -#include <limits> // for std::numeric_limits; | |
50 | +#include <libdefect/limits.hpp> // for std::numeric_limits (with fixes); | |
52 | 51 | #include "iterator_trait.hpp" // for enable_for_input_iterator_t; |
53 | 52 | |
54 | 53 | namespace ystdex |
@@ -1025,7 +1024,7 @@ | ||
1025 | 1024 | |
1026 | 1025 | for(bool init(true); ; init = {}) |
1027 | 1026 | { |
1028 | - // NOTE: [first, mid) and [mid, last) are sorted and non-empty. | |
1027 | + // NOTE: [first, mid) and [mid, last) are sorted and nonempty. | |
1029 | 1028 | // XXX: Use %YB_VerifyIterator? |
1030 | 1029 | yverify(mid != end()); |
1031 | 1030 | yverify(first != end()); |
@@ -1200,8 +1199,8 @@ | ||
1200 | 1199 | // %std::allocator_traits::is_always_equal trait of the internal node. In |
1201 | 1200 | // ISO C++17 there is no explicit exception specification. |
1202 | 1201 | list(list&& x, const allocator_type& a) |
1203 | - yimpl(ynoexcept(is_nothrow_constructible< | |
1204 | - rep_type, rep_type&&, const allocator_type&>())) | |
1202 | + yimpl(ynoexcept(is_nothrow_constructible<rep_type, rep_type&&, | |
1203 | + const allocator_type&>())) | |
1205 | 1204 | : rep(std::move(x.rep), a) |
1206 | 1205 | {} |
1207 | 1206 |
@@ -1,23 +1,22 @@ | ||
1 | 1 | /* |
2 | - © 2011-2016, 2018-2023 FrankHB. | |
2 | + © 2011-2016, 2018-2024 FrankHB. | |
3 | 3 | |
4 | - This file is part of the YSLib project, and may only be used, | |
5 | - modified, and distributed under the terms of the YSLib project | |
6 | - license, LICENSE.TXT. By continuing to use, modify, or distribute | |
7 | - this file you indicate that you have read the license and | |
8 | - understand and accept it fully. | |
4 | + This file is part of the YSLib project, and may only be used, modified, | |
5 | + and distributed under the terms of the YSLib project license. | |
6 | + By continuing to use, modify, or distribute this file you indicate that | |
7 | + you have read the license and understand and accept it fully. | |
9 | 8 | */ |
10 | 9 | |
11 | 10 | /*! \file meta.hpp |
12 | 11 | \ingroup YStandardEx |
13 | 12 | \brief 通用元编程设施。 |
14 | -\version r2119 | |
13 | +\version r2562 | |
15 | 14 | \author FrankHB <frankhb1989@gmail.com> |
16 | 15 | \since build 832 |
17 | 16 | \par 创建时间: |
18 | 17 | 2018-07-23 17:22:28 +0800 |
19 | 18 | \par 修改时间: |
20 | - 2023-04-12 12:08 +0800 | |
19 | + 2024-04-05 03:31 +0800 | |
21 | 20 | \par 文本编码: |
22 | 21 | UTF-8 |
23 | 22 | \par 模块名称: |
@@ -30,9 +29,8 @@ | ||
30 | 29 | |
31 | 30 | #include "type_inspection.hpp" // for "type_inspection.hpp", <type_traits>, |
32 | 31 | // __cpp_lib_transformation_trait_aliases, __cpp_lib_remove_cvref, |
33 | -// __cpp_lib_void_t, __cpp_lib_type_identity, true_, is_same, is_convertible, | |
34 | -// or_, nor_, and_, is_class, is_union, is_trivial, not_, is_final, size_t_, | |
35 | -// is_unsigned; | |
32 | +// __cpp_lib_void_t, __cpp_lib_type_identity, _t, true_, is_same, | |
33 | +// is_convertible, size_t_, is_unsigned; | |
36 | 34 | |
37 | 35 | /*! |
38 | 36 | \brief \c \<type_traits> 特性测试宏。 |
@@ -85,14 +83,6 @@ | ||
85 | 83 | { |
86 | 84 | |
87 | 85 | /*! |
88 | -\ingroup metafunctions | |
89 | -\brief 嵌套类型别名。 | |
90 | -\since build 649 | |
91 | -*/ | |
92 | -template<class _type> | |
93 | -using _t = typename _type::type; | |
94 | - | |
95 | -/*! | |
96 | 86 | \brief 包含 ISO C++ 2011 引入的名称的命名空间。 |
97 | 87 | \since build 607 |
98 | 88 | */ |
@@ -112,8 +102,45 @@ | ||
112 | 102 | using std::add_lvalue_reference; |
113 | 103 | using std::add_rvalue_reference; |
114 | 104 | |
105 | +#if YB_Impl_ext_int128 | |
106 | +/*! | |
107 | +\ingroup YBase_replacement_features unary_type_traits | |
108 | +\since build 983 | |
109 | +*/ | |
110 | +//!@{ | |
111 | +# define YB_Impl_Meta_tt_primary(_n) \ | |
112 | + template<typename _type> \ | |
113 | + struct _n : std::_n<_type> \ | |
114 | + {}; | |
115 | +# define YB_Impl_Meta_tt_spec(_n, _t, _t2) \ | |
116 | + template<> \ | |
117 | + struct _n<_t> \ | |
118 | + { \ | |
119 | + using type = _t2; \ | |
120 | + }; | |
121 | +# define YB_Impl_Meta_tt_specs(_n, _t, _t2) \ | |
122 | + YB_Impl_Meta_tt_spec(_n, _t, _t2) \ | |
123 | + YB_Impl_Meta_tt_spec(_n, const _t, const _t2) \ | |
124 | + YB_Impl_Meta_tt_spec(_n, volatile _t, volatile _t2) \ | |
125 | + YB_Impl_Meta_tt_spec(_n, const volatile _t, const volatile _t2) | |
126 | +# define YB_Impl_Meta_tt_ext_int128(_n, _t) \ | |
127 | + YB_Impl_Meta_tt_primary(_n) \ | |
128 | + YB_Impl_Meta_tt_spec(_n, int128_t, _t) \ | |
129 | + YB_Impl_Meta_tt_spec(_n, uint128_t, _t) | |
130 | + | |
131 | +YB_Impl_Meta_tt_ext_int128(make_signed, int128_t) | |
132 | + | |
133 | +YB_Impl_Meta_tt_ext_int128(make_unsigned, uint128_t) | |
134 | + | |
135 | +# undef YB_Impl_Meta_tt_ext_int128 | |
136 | +# undef YB_Impl_Meta_tt_specs | |
137 | +# undef YB_Impl_Meta_tt_spec | |
138 | +# undef YB_Impl_Meta_tt_primary | |
139 | +//!@} | |
140 | +#else | |
115 | 141 | using std::make_signed; |
116 | 142 | using std::make_unsigned; |
143 | +#endif | |
117 | 144 | |
118 | 145 | using std::remove_extent; |
119 | 146 | using std::remove_all_extents; |
@@ -178,76 +205,76 @@ | ||
178 | 205 | //! \since build 340 |
179 | 206 | //!@{ |
180 | 207 | template<typename _type> |
181 | -using remove_const_t = typename remove_const<_type>::type; | |
182 | - | |
183 | -template<typename _type> | |
184 | -using remove_volatile_t = typename remove_volatile<_type>::type; | |
208 | +using remove_const_t = _t<remove_const<_type>>; | |
185 | 209 | |
186 | 210 | template<typename _type> |
187 | -using remove_cv_t = typename remove_cv<_type>::type; | |
211 | +using remove_volatile_t = _t<remove_volatile<_type>>; | |
188 | 212 | |
189 | 213 | template<typename _type> |
190 | -using add_const_t = typename add_const<_type>::type; | |
214 | +using remove_cv_t = _t<remove_cv<_type>>; | |
191 | 215 | |
192 | 216 | template<typename _type> |
193 | -using add_volatile_t = typename add_volatile<_type>::type; | |
217 | +using add_const_t = _t<add_const<_type>>; | |
194 | 218 | |
195 | 219 | template<typename _type> |
196 | -using add_cv_t = typename add_cv<_type>::type; | |
220 | +using add_volatile_t = _t<add_volatile<_type>>; | |
221 | + | |
222 | +template<typename _type> | |
223 | +using add_cv_t = _t<add_cv<_type>>; | |
197 | 224 | |
198 | 225 | |
199 | 226 | template<typename _type> |
200 | -using remove_reference_t = typename remove_reference<_type>::type; | |
227 | +using remove_reference_t = _t<remove_reference<_type>>; | |
201 | 228 | |
202 | 229 | template<typename _type> |
203 | -using add_lvalue_reference_t = typename add_lvalue_reference<_type>::type; | |
230 | +using add_lvalue_reference_t = _t<add_lvalue_reference<_type>>; | |
204 | 231 | |
205 | 232 | template<typename _type> |
206 | -using add_rvalue_reference_t = typename add_rvalue_reference<_type>::type; | |
233 | +using add_rvalue_reference_t = _t<add_rvalue_reference<_type>>; | |
207 | 234 | |
208 | 235 | |
209 | 236 | template<typename _type> |
210 | -using make_signed_t = typename make_signed<_type>::type; | |
237 | +using make_signed_t = _t<make_signed<_type>>; | |
211 | 238 | |
212 | 239 | template<typename _type> |
213 | -using make_unsigned_t = typename make_unsigned<_type>::type; | |
240 | +using make_unsigned_t = _t<make_unsigned<_type>>; | |
214 | 241 | |
215 | 242 | |
216 | 243 | template<typename _type> |
217 | -using remove_extent_t = typename remove_extent<_type>::type; | |
244 | +using remove_extent_t = _t<remove_extent<_type>>; | |
218 | 245 | |
219 | 246 | template<typename _type> |
220 | -using remove_all_extents_t = typename remove_all_extents<_type>::type; | |
247 | +using remove_all_extents_t = _t<remove_all_extents<_type>>; | |
221 | 248 | |
222 | 249 | |
223 | 250 | template<typename _type> |
224 | -using remove_pointer_t = typename remove_pointer<_type>::type; | |
251 | +using remove_pointer_t = _t<remove_pointer<_type>>; | |
225 | 252 | |
226 | 253 | template<typename _type> |
227 | -using add_pointer_t = typename add_pointer<_type>::type; | |
254 | +using add_pointer_t = _t<add_pointer<_type>>; | |
228 | 255 | |
229 | 256 | |
230 | 257 | template<size_t _vLen, |
231 | 258 | size_t _vAlign = yalignof(typename aligned_storage<_vLen>::type)> |
232 | -using aligned_storage_t = typename aligned_storage<_vLen, _vAlign>::type; | |
259 | +using aligned_storage_t = _t<aligned_storage<_vLen, _vAlign>>; | |
233 | 260 | //!@} |
234 | 261 | |
235 | 262 | //! \since build 339 |
236 | 263 | //!@{ |
237 | 264 | template<size_t _vLen, typename... _types> |
238 | -using aligned_union_t = typename aligned_union<_vLen, _types...>::type; | |
265 | +using aligned_union_t = _t<aligned_union<_vLen, _types...>>; | |
239 | 266 | |
240 | 267 | template<typename _type> |
241 | -using decay_t = typename decay<_type>::type; | |
268 | +using decay_t = _t<decay<_type>>; | |
242 | 269 | |
243 | 270 | template<bool _bCond, typename _type = void> |
244 | -using enable_if_t = typename enable_if<_bCond, _type>::type; | |
271 | +using enable_if_t = _t<enable_if<_bCond, _type>>; | |
245 | 272 | |
246 | 273 | template<bool _bCond, typename _type, typename _type2> |
247 | -using conditional_t = typename conditional<_bCond, _type, _type2>::type; | |
274 | +using conditional_t = _t<conditional<_bCond, _type, _type2>>; | |
248 | 275 | |
249 | 276 | template<typename _type> |
250 | -using underlying_type_t = typename underlying_type<_type>::type; | |
277 | +using underlying_type_t = _t<underlying_type<_type>>; | |
251 | 278 | //!@} |
252 | 279 | #endif |
253 | 280 | //!@} |
@@ -297,8 +324,15 @@ | ||
297 | 324 | */ |
298 | 325 | //!@{ |
299 | 326 | template<typename _type> |
327 | +#if __has_builtin(__remove_cvref) | |
328 | +struct remove_cvref | |
329 | +{ | |
330 | + using type = __remove_cvref(_type); | |
331 | +}; | |
332 | +#else | |
300 | 333 | struct remove_cvref : remove_cv<remove_reference_t<_type>> |
301 | 334 | {}; |
335 | +#endif | |
302 | 336 | |
303 | 337 | //! \since build 833 |
304 | 338 | template<typename _type> |
@@ -372,7 +406,7 @@ | ||
372 | 406 | |
373 | 407 | //! \since build 340 |
374 | 408 | template<typename... _types> |
375 | -using common_type_t = typename common_type<_types...>::type; | |
409 | +using common_type_t = _t<common_type<_types...>>; | |
376 | 410 | //!@} |
377 | 411 | //!@} |
378 | 412 | #endif |
@@ -414,7 +448,7 @@ | ||
414 | 448 | using well_formed_t = _type; |
415 | 449 | #else |
416 | 450 | template<typename _type, typename... _types> |
417 | -using well_formed_t = typename always<_type>::template apply<_types...>::type; | |
451 | +using well_formed_t = _t<always<_type>::template apply<_types...>>; | |
418 | 452 | #endif |
419 | 453 | |
420 | 454 | //! \since build 831 |
@@ -539,6 +573,7 @@ | ||
539 | 573 | |
540 | 574 | } // namespace details; |
541 | 575 | #endif |
576 | +#undef YB_Impl_TypeTraits_has_cpp20_common_type | |
542 | 577 | |
543 | 578 | |
544 | 579 | /*! |
@@ -552,6 +587,7 @@ | ||
552 | 587 | |
553 | 588 | |
554 | 589 | /*! |
590 | +\ingroup YBase_replacement_features | |
555 | 591 | \brief 不接受任意参数类型构造的类型。 |
556 | 592 | \see WG21 N4502 6.6 。 |
557 | 593 | \since build 649 |
@@ -591,18 +627,6 @@ | ||
591 | 627 | using type = _gOp<_tParams...>; |
592 | 628 | }; |
593 | 629 | |
594 | - | |
595 | -//! \since build 867 | |
596 | -//!@{ | |
597 | -template<typename _type1, typename _type2, bool = is_same<_type1, _type2>{}> | |
598 | -struct is_same_or_convertible : is_convertible<_type1, _type2> | |
599 | -{}; | |
600 | - | |
601 | -template<typename _type1, typename _type2> | |
602 | -struct is_same_or_convertible<_type1, _type2, true> : true_ | |
603 | -{}; | |
604 | -//!@} | |
605 | - | |
606 | 630 | } // namespace details; |
607 | 631 | |
608 | 632 | //! \ingroup YBase_replacement_features |
@@ -631,382 +655,6 @@ | ||
631 | 655 | = is_convertible<detected_t<_gOp, _tParams...>, _tTo>; |
632 | 656 | //!@} |
633 | 657 | //!@} |
634 | - | |
635 | - | |
636 | -/*! | |
637 | -\ingroup unary_type_traits | |
638 | -\tparam _type 需要判断特征的类型参数。 | |
639 | -*/ | |
640 | -//!@{ | |
641 | -//! \note 以下参数可能是 cv 修饰的类型,结果和去除 cv 修饰符的类型一致。 | |
642 | -//!@{ | |
643 | -/*! | |
644 | -\brief 判断是否为未知大小的数组类型。 | |
645 | -\since build 651 | |
646 | -*/ | |
647 | -template<typename _type> | |
648 | -struct is_array_of_unknown_bound | |
649 | - : bool_<is_array<_type>() && extent<_type>() == 0> | |
650 | -{}; | |
651 | - | |
652 | - | |
653 | -/*! | |
654 | -\brief 判断指定类型是否为对象或 void 类型。 | |
655 | -\since build 630 | |
656 | -*/ | |
657 | -template<typename _type> | |
658 | -struct is_object_or_void : or_<is_object<_type>, is_void<_type>> | |
659 | -{}; | |
660 | - | |
661 | - | |
662 | -//! \since build 694 | |
663 | -namespace details | |
664 | -{ | |
665 | - | |
666 | -template<typename _type> | |
667 | -struct is_referenceable_function : false_ | |
668 | -{}; | |
669 | - | |
670 | -template<typename _tRes, typename... _tParams ynoexcept_param(ne)> | |
671 | -struct is_referenceable_function<_tRes(_tParams...) ynoexcept_qual(ne)> : true_ | |
672 | -{}; | |
673 | - | |
674 | -template<typename _tRes, typename... _tParams ynoexcept_param(ne)> | |
675 | -struct is_referenceable_function<_tRes(_tParams..., ...) ynoexcept_qual(ne)> | |
676 | - : true_ | |
677 | -{}; | |
678 | - | |
679 | -} // namespace details; | |
680 | - | |
681 | -/*! | |
682 | -\brief 判断指定类型是否为可引用类型。 | |
683 | -\see ISO C++11 17.3.20 [defns.referenceable] 。 | |
684 | -\since build 694 | |
685 | -*/ | |
686 | -template<typename _type> | |
687 | -struct is_referenceable : or_<is_object<_type>, is_reference<_type>, | |
688 | - details::is_referenceable_function<_type>> | |
689 | -{}; | |
690 | - | |
691 | - | |
692 | -/*! | |
693 | -\brief 判断指定类型是否可作为返回类型。 | |
694 | -\note 即排除数组类型、抽象类类型和函数类型的所有类型。 | |
695 | -\see ISO C++11 8.3.5/8 和 ISO C++11 10.4/3 。 | |
696 | -\since build 333 | |
697 | -*/ | |
698 | -template<typename _type> | |
699 | -struct is_returnable | |
700 | - : nor_<is_array<_type>, is_abstract<_type>, is_function<_type>> | |
701 | -{}; | |
702 | - | |
703 | - | |
704 | -/*! | |
705 | -\brief 判断指定类型是否是类类型。 | |
706 | -\since build 588 | |
707 | -*/ | |
708 | -template<typename _type> | |
709 | -struct is_class_type | |
710 | - : or_<is_class<_type>, is_union<_type>> | |
711 | -{}; | |
712 | - | |
713 | - | |
714 | -/*! | |
715 | -\brief 判断类型是否为非 const 对象类型。 | |
716 | -\since build 650 | |
717 | -*/ | |
718 | -template<typename _type> | |
719 | -struct is_nonconst_object | |
720 | - : and_<is_object<_type>, is_same<add_const_t<_type>, _type>> | |
721 | -{}; | |
722 | - | |
723 | - | |
724 | -//! \since build 630 | |
725 | -//!@{ | |
726 | -//! \brief 判断指定类型是否是指向对象类型的指针。 | |
727 | -template<typename _type> | |
728 | -struct is_pointer_to_object | |
729 | - : and_<is_pointer<_type>, is_object<remove_pointer_t<_type>>> | |
730 | -{}; | |
731 | - | |
732 | - | |
733 | -//! \brief 判断指定类型是否是指向对象类型的指针。 | |
734 | -template<typename _type> | |
735 | -struct is_object_pointer | |
736 | - : and_<is_pointer<_type>, is_object_or_void<remove_pointer_t<_type>>> | |
737 | -{}; | |
738 | - | |
739 | - | |
740 | -//! \brief 判断指定类型是否是指向函数类型的指针。 | |
741 | -template<typename _type> | |
742 | -struct is_function_pointer | |
743 | - : and_<is_pointer<_type>, is_function<remove_pointer_t<_type>>> | |
744 | -{}; | |
745 | -//!@} | |
746 | - | |
747 | - | |
748 | -//! \since build 333 | |
749 | -//!@{ | |
750 | -//! \brief 判断指定类型是否是指向类类型的指针。 | |
751 | -template<typename _type> | |
752 | -struct is_class_pointer | |
753 | - : and_<is_pointer<_type>, is_class<remove_pointer_t<_type>>> | |
754 | -{}; | |
755 | - | |
756 | - | |
757 | -//! \brief 判断指定类型是否是类类型左值引用。 | |
758 | -template<typename _type> | |
759 | -struct is_lvalue_class_reference | |
760 | - : and_<is_lvalue_reference<_type>, is_class<remove_reference_t<_type>>> | |
761 | -{}; | |
762 | - | |
763 | - | |
764 | -//! \brief 判断指定类型是否是类类型右值引用。 | |
765 | -template<typename _type> | |
766 | -struct is_rvalue_class_reference | |
767 | - : and_<is_rvalue_reference<_type>, is_class<remove_reference_t<_type>>> | |
768 | -{}; | |
769 | -//!@} | |
770 | - | |
771 | - | |
772 | -/*! | |
773 | -\pre remove_all_extents\<_type> 是完整类型或(可能 cv 修饰的) \c void 。 | |
774 | -\see ISO C++17 [class.prop]/2 。 | |
775 | -\since build 853 | |
776 | -*/ | |
777 | -//!@{ | |
778 | -/*! | |
779 | -\brief 判断指定类型是否是平凡的非联合类类型。 | |
780 | -\note 注意和 ISO C++ 的 \c std::is_class 类似,排除联合。 | |
781 | -*/ | |
782 | -template<typename _type> | |
783 | -struct is_trivial_class : and_<is_trivial<_type>, is_class<_type>> | |
784 | -{}; | |
785 | - | |
786 | -template<typename _type> | |
787 | -struct is_trivial_class_type : and_<is_trivial<_type>, is_class_type<_type>> | |
788 | -{}; | |
789 | - | |
790 | -//! \brief 判断指定类型是否是平凡的联合类型。 | |
791 | -template<typename _type> | |
792 | -struct is_trivial_union : and_<is_trivial<_type>, is_union<_type>> | |
793 | -{}; | |
794 | -//!@} | |
795 | - | |
796 | - | |
797 | -/*! | |
798 | -\brief 判断指定类型是否是可被继承的类类型。 | |
799 | -\since build 940 | |
800 | -*/ | |
801 | -template<typename _type> | |
802 | -struct is_inheritable_class : and_<is_class<_type>, not_<is_final<_type>>> | |
803 | -{}; | |
804 | -//!@} | |
805 | - | |
806 | - | |
807 | -/*! | |
808 | -\brief 判断指定类型是否为 const 或 volatile 类型。 | |
809 | -\since build 590 | |
810 | -*/ | |
811 | -template<typename _type> | |
812 | -struct is_cv : or_<is_const<_type>, is_volatile<_type>> | |
813 | -{}; | |
814 | -//!@} | |
815 | - | |
816 | - | |
817 | -/*! | |
818 | -\brief 判断指定类型是否可分解为一个参数为类型的模板和类型参数。 | |
819 | -\since build 683 | |
820 | -*/ | |
821 | -//!@{ | |
822 | -template<typename> | |
823 | -struct is_decomposable : false_ | |
824 | -{}; | |
825 | - | |
826 | -template<template<typename...> class _gOp, typename... _types> | |
827 | -struct is_decomposable<_gOp<_types...>> : true_ | |
828 | -{}; | |
829 | -//!@} | |
830 | - | |
831 | - | |
832 | -/*! | |
833 | -\pre remove_all_extents\<_type> 是完整类型、(可能 cv 修饰的) \c void , | |
834 | - 或未知大小的数组。 | |
835 | -\since build 630 | |
836 | -*/ | |
837 | -//!@{ | |
838 | -template<typename _type> | |
839 | -struct is_copyable | |
840 | - : and_<is_copy_constructible<_type>, is_copy_assignable<_type>> | |
841 | -{}; | |
842 | - | |
843 | - | |
844 | -template<typename _type> | |
845 | -struct is_moveable | |
846 | - : and_<is_move_constructible<_type>, is_move_assignable<_type>> | |
847 | -{}; | |
848 | - | |
849 | - | |
850 | -template<typename _type> | |
851 | -struct is_nothrow_copyable : and_<is_nothrow_copy_constructible<_type>, | |
852 | - is_nothrow_copy_assignable<_type>> | |
853 | -{}; | |
854 | - | |
855 | - | |
856 | -template<typename _type> | |
857 | -struct is_nothrow_moveable : and_<is_nothrow_move_constructible<_type>, | |
858 | - is_nothrow_move_assignable<_type>> | |
859 | -{}; | |
860 | - | |
861 | - | |
862 | -template<typename _type> | |
863 | -struct is_trivially_copyable : and_<is_trivially_copy_constructible<_type>, | |
864 | - is_trivially_copy_assignable<_type>> | |
865 | -{}; | |
866 | - | |
867 | - | |
868 | -template<typename _type> | |
869 | -struct is_trivially_moveable : and_<is_trivially_move_constructible<_type>, | |
870 | - is_trivially_move_assignable<_type>> | |
871 | -{}; | |
872 | - | |
873 | - | |
874 | -/*! | |
875 | -\brief 判断指定类型是否为可复制构造但不可无抛出异常地转移构造的类型。 | |
876 | -\note 和 std::move_if_noexcept 需要选择复制的条件相同。 | |
877 | -\since build 865 | |
878 | -*/ | |
879 | -template<typename _type> | |
880 | -struct is_throwing_move_copyable : and_<is_copy_constructible<_type>, | |
881 | - not_<is_nothrow_move_constructible<_type>>> | |
882 | -{}; | |
883 | -//!@} | |
884 | -//!@} | |
885 | - | |
886 | - | |
887 | -//! \note 参数可以是不完整类型。 | |
888 | -//!@{ | |
889 | -//! \ingroup type_traits_operations | |
890 | -//!@{ | |
891 | -/*! | |
892 | -\brief 判断指定类型是否已退化为指定类型。 | |
893 | -\since build 841 | |
894 | -*/ | |
895 | -template<typename _type, typename _tTo = _type> | |
896 | -struct is_decayed : is_same<_type, decay_t<_tTo>> | |
897 | -{}; | |
898 | - | |
899 | - | |
900 | -/*! | |
901 | -\brief 判断指定类型是否为无限定的指定类型。 | |
902 | -\since build 865 | |
903 | -*/ | |
904 | -template<typename _type, typename _tTo = _type> | |
905 | -struct is_unqualified : is_same<_type, remove_cv_t<_tTo>> | |
906 | -{}; | |
907 | -//!@} | |
908 | - | |
909 | - | |
910 | -//! \ingroup unary_type_trait | |
911 | -//!@{ | |
912 | -/*! | |
913 | -\brief 判断类型是否为非 const 对象类型。 | |
914 | -\since build 867 | |
915 | -*/ | |
916 | -template<typename _type> | |
917 | -struct is_unqualified_object : and_<is_object<_type>, is_unqualified<_type>> | |
918 | -{}; | |
919 | - | |
920 | - | |
921 | -/*! | |
922 | -\brief 判断类型是否为非 const 对象的数组类型。 | |
923 | -\since build 972 | |
924 | -*/ | |
925 | -template<typename _type> | |
926 | -struct is_array_of_unqualified_object : and_<is_array<_type>, | |
927 | - is_unqualified_object<remove_extent_t<_type>>> | |
928 | -{}; | |
929 | -//!@} | |
930 | -//!@} | |
931 | - | |
932 | - | |
933 | -//! \ingroup binary_type_traits | |
934 | -//!@{ | |
935 | -/*! | |
936 | -\brief 判断指定类型之间是否相同或可转换。 | |
937 | -\note 类似 is_convertible ,但不要求完整类型。 | |
938 | -\since build 850 | |
939 | -*/ | |
940 | -template<typename _type1, typename _type2> | |
941 | -struct is_same_or_convertible : details::is_same_or_convertible<_type1, _type2> | |
942 | -{}; | |
943 | - | |
944 | - | |
945 | -/*! | |
946 | -\brief 判断指定类型之间是否相同或可互相转换。 | |
947 | -\since build 575 | |
948 | -*/ | |
949 | -template<typename _type1, typename _type2> | |
950 | -struct is_interoperable : or_<is_same_or_convertible<_type1, _type2>, | |
951 | - is_convertible<_type2, _type1>> | |
952 | -{}; | |
953 | - | |
954 | - | |
955 | -//! \since build 832 | |
956 | -//!@{ | |
957 | -//! \brief 判断指定类型是否可被指定参数类型构造且要求显式构造。 | |
958 | -template <typename _type, typename _tFrom> | |
959 | -struct is_explicitly_constructible : and_<is_constructible<_type, _tFrom>, | |
960 | - not_<is_convertible<_tFrom, _type>>> | |
961 | -{}; | |
962 | - | |
963 | - | |
964 | -//! \brief 判断指定类型是否可被指定参数类型无异常抛出构造且要求显式构造。 | |
965 | -template <typename _type, typename _tFrom> | |
966 | -struct is_explicitly_nothrow_constructible : and_<is_nothrow_constructible< | |
967 | - _type, _tFrom>, not_<is_convertible<_tFrom, _type>>> | |
968 | -{}; | |
969 | - | |
970 | - | |
971 | -//! \brief 判断指定类型是否可被指定参数类型构造且可隐式构造。 | |
972 | -template <typename _type, typename _tFrom> | |
973 | -struct is_implicitly_constructible : and_<is_constructible<_type, _tFrom>, | |
974 | - is_convertible<_tFrom, _type>> | |
975 | -{}; | |
976 | - | |
977 | - | |
978 | -//! \brief 判断指定类型是否可被指定参数类型无异常抛出构造且可隐式构造。 | |
979 | -template <typename _type, typename _tFrom> | |
980 | -struct is_implicitly_nothrow_constructible : and_<is_nothrow_constructible< | |
981 | - _type, _tFrom>, is_convertible<_tFrom, _type>> | |
982 | -{}; | |
983 | -//!@} | |
984 | - | |
985 | - | |
986 | -/*! | |
987 | -\brief 判断第一参数和第二参数指定的参数类型相同。 | |
988 | -\since build 865 | |
989 | -*/ | |
990 | -template<typename _type, typename _tParam> | |
991 | -struct is_same_param : is_same<_type&, decay_t<_tParam>&> | |
992 | -{}; | |
993 | -//!@} | |
994 | - | |
995 | - | |
996 | -/*! | |
997 | -\ingroup metafunctions | |
998 | -\since build 671 | |
999 | -*/ | |
1000 | -//!@{ | |
1001 | -//! \brief 判断第一参数和之后的参数指定的类型相同。 | |
1002 | -template<typename _type, typename... _types> | |
1003 | -struct are_same : and_<is_same<_type, _types>...> | |
1004 | -{}; | |
1005 | - | |
1006 | -//! \brief 判断第一参数在之后参数指定的类型中出现。 | |
1007 | -template<typename _type, typename... _types> | |
1008 | -struct is_in_types : or_<is_same<_type, _types>...> | |
1009 | -{}; | |
1010 | 658 | //!@} |
1011 | 659 | |
1012 | 660 |
@@ -1087,24 +735,73 @@ | ||
1087 | 735 | //!@} |
1088 | 736 | |
1089 | 737 | |
1090 | -/*! | |
1091 | -\ingroup transformation_traits | |
1092 | -\since build 942 | |
1093 | -*/ | |
1094 | -//!@{ | |
738 | +//! \since build 942 | |
1095 | 739 | template<typename... _types> |
1096 | 740 | using empty_pack_t = bool_<sizeof...(_types) == 0>; |
1097 | 741 | |
742 | +//! \since build 942 | |
1098 | 743 | template<typename... _types> |
1099 | 744 | using sizeof_pack_t = size_t_<sizeof...(_types)>; |
745 | + | |
746 | + | |
747 | +//! \since build 983 | |
748 | +//!@{ | |
749 | +/*! | |
750 | +\brief 复制第二模板参数的 cv 限定符到第一模板参数指定的类型。 | |
751 | +\see https://www.boost.org/doc/libs/1_84_0/libs/type_traits/doc/html/boost_typetraits/reference/copy_cv.html 。 | |
752 | +*/ | |
753 | +//!@{ | |
754 | +template<typename _type, typename _type2> | |
755 | +struct copy_cv | |
756 | +{ | |
757 | +private: | |
758 | + using ctype = cond_t<is_const<_type2>, add_const<_type>, _type>; | |
759 | + | |
760 | +public: | |
761 | + using type = cond_t<is_volatile<_type2>, add_volatile_t<ctype>, ctype>; | |
762 | +}; | |
763 | + | |
764 | +template<typename _type, typename _type2> | |
765 | +using copy_cv_t = _t<copy_cv<_type, _type2>>; | |
1100 | 766 | //!@} |
1101 | 767 | |
768 | + | |
1102 | 769 | /*! |
1103 | -\ingroup unary_type_traits | |
1104 | -\since build 843 | |
770 | +\brief 复制第二模板参数的引用类型限定符到第一模板参数指定的类型。 | |
771 | +\note 结果类型中的引用限定符按引用折叠规则合并两个模板参数中的引用限定符。 | |
772 | +\see https://www.boost.org/doc/libs/1_84_0/libs/type_traits/doc/html/boost_typetraits/reference/copy_reference.html 。 | |
1105 | 773 | */ |
1106 | -template<typename _type> | |
1107 | -using sizeof_t = size_t_<sizeof(_type)>; | |
774 | +//!@{ | |
775 | +template<typename _type, typename _type2> | |
776 | +struct copy_reference | |
777 | +{ | |
778 | + using type = cond_t<is_rvalue_reference<_type2>, | |
779 | + add_rvalue_reference_t<_type>, cond_t<is_lvalue_reference<_type2>, | |
780 | + add_lvalue_reference<_type>, _type>>; | |
781 | +}; | |
782 | + | |
783 | +template<typename _type, typename _type2> | |
784 | +using copy_reference_t = _t<copy_reference<_type, _type2>>; | |
785 | +//!@} | |
786 | + | |
787 | + | |
788 | +/*! | |
789 | +\brief 复制第二模板参数的 cv 和引用类型限定符到第一模板参数指定的类型。 | |
790 | +\note 和 \c boost::copy_cv_ref 不同,遵循 remove_cvref 的命名,不添加过多 \c _ 。 | |
791 | +\see https://www.boost.org/doc/libs/1_84_0/libs/type_traits/doc/html/boost_typetraits/reference/copy_cv_ref.html 。 | |
792 | +*/ | |
793 | +//!@{ | |
794 | +template<typename _type, typename _type2> | |
795 | +struct copy_cvref | |
796 | +{ | |
797 | + using type = copy_reference_t< | |
798 | + copy_cv_t<_type, remove_reference_t<_type2>>, _type2>; | |
799 | +}; | |
800 | + | |
801 | +template<typename _type, typename _type2> | |
802 | +using copy_cvref_t = _t<copy_cvref<_type, _type2>>; | |
803 | +//!@} | |
804 | +//!@} | |
1108 | 805 | |
1109 | 806 | |
1110 | 807 | /*! |
@@ -1155,6 +852,14 @@ | ||
1155 | 852 | = enable_if_t<is_same_param<_type1, _type2>{}, _type>; |
1156 | 853 | |
1157 | 854 | /*! |
855 | +\brief 启用浮点数类型参数的重载。 | |
856 | +\since build 983 | |
857 | +*/ | |
858 | +template<typename _tParam, typename _type = remove_cvref_t<_tParam>> | |
859 | +using enable_if_floating_point_t | |
860 | + = enable_if_t<is_floating_point<remove_cvref_t<_tParam>>{}, _type>; | |
861 | + | |
862 | +/*! | |
1158 | 863 | \brief 启用无符号类型参数的重载。 |
1159 | 864 | \since build 933 |
1160 | 865 | */ |
@@ -1,23 +1,22 @@ | ||
1 | 1 | /* |
2 | - © 2015-2023 FrankHB. | |
2 | + © 2015-2024 FrankHB. | |
3 | 3 | |
4 | - This file is part of the YSLib project, and may only be used, | |
5 | - modified, and distributed under the terms of the YSLib project | |
6 | - license, LICENSE.TXT. By continuing to use, modify, or distribute | |
7 | - this file you indicate that you have read the license and | |
8 | - understand and accept it fully. | |
4 | + This file is part of the YSLib project, and may only be used, modified, | |
5 | + and distributed under the terms of the YSLib project license. | |
6 | + By continuing to use, modify, or distribute this file you indicate that | |
7 | + you have read the license and understand and accept it fully. | |
9 | 8 | */ |
10 | 9 | |
11 | 10 | /*! \file optional.h |
12 | 11 | \ingroup YStandardEx |
13 | 12 | \brief 可选值包装类型。 |
14 | -\version r1424 | |
13 | +\version r1435 | |
15 | 14 | \author FrankHB <frankhb1989@gmail.com> |
16 | 15 | \since build 590 |
17 | 16 | \par 创建时间: |
18 | 17 | 2015-04-09 21:35:21 +0800 |
19 | 18 | \par 修改时间: |
20 | - 2023-02-07 22:08 +0800 | |
19 | + 2024-03-30 23:43 +0800 | |
21 | 20 | \par 文本编码: |
22 | 21 | UTF-8 |
23 | 22 | \par 模块名称: |
@@ -55,7 +54,7 @@ | ||
55 | 54 | #if YB_Has_optional != 1 |
56 | 55 | # include "operators.hpp" // for or_, is_constructible, |
57 | 56 | // is_trivially_destructible, is_cv, std::move, empty_base, |
58 | -// is_nothrow_moveable, and_, nullptr_t, remove_cv_t, totally_ordered, nand_, | |
57 | +// is_nothrow_movable, and_, nullptr_t, remove_cv_t, totally_ordered, nand_, | |
59 | 58 | // is_reference, is_same, is_nothrow_destructible, is_object, enable_if_t, |
60 | 59 | // not_, decay_t, is_nothrow_swappable, ystdex::addressof, is_copyable; |
61 | 60 | # include <initializer_list> // for std::initializer_list; |
@@ -192,7 +191,7 @@ | ||
192 | 191 | } |
193 | 192 | //! \since build 630 |
194 | 193 | optional_base& |
195 | - operator=(optional_base&& s) ynoexcept(is_nothrow_moveable<_type>()) | |
194 | + operator=(optional_base&& s) ynoexcept(is_nothrow_movable<_type>()) | |
196 | 195 | { |
197 | 196 | return assign(std::move(s.value)); |
198 | 197 | } |
@@ -201,7 +200,7 @@ | ||
201 | 200 | template<typename _tParam> |
202 | 201 | optional_base& |
203 | 202 | assign(_tParam&& arg) ynoexcept(and_<is_rvalue_reference<_tParam&&>, |
204 | - is_nothrow_moveable<_type>>()) | |
203 | + is_nothrow_movable<_type>>()) | |
205 | 204 | { |
206 | 205 | if(has_value() && arg.has_value()) |
207 | 206 | value = yforward(arg); |
@@ -344,7 +343,7 @@ | ||
344 | 343 | \ingroup YBase_replacement_features |
345 | 344 | \brief 可选值对象包装。 |
346 | 345 | \note 值语义。基本接口和语义同 std::experimental::optional 提议 |
347 | - 和 boost::optional (对应接口以前者为准)。 | |
346 | + 和 boost::optional(对应接口以前者为准)。 | |
348 | 347 | \warning 非虚析构。 |
349 | 348 | \see WG21 N4606 20.6.3[optional.object] 。 |
350 | 349 | \todo allocator_arg 支持。 |
@@ -477,7 +476,7 @@ | ||
477 | 476 | } |
478 | 477 | //! \since build 630 |
479 | 478 | optional& |
480 | - operator=(optional&& o) ynoexcept(is_nothrow_moveable<_type>()) | |
479 | + operator=(optional&& o) ynoexcept(is_nothrow_movable<_type>()) | |
481 | 480 | { |
482 | 481 | get_base() = std::move(o.get_base()); |
483 | 482 | return *this; |
@@ -1,23 +1,22 @@ | ||
1 | 1 | /* |
2 | 2 | © 2016-2019, 2021, 2023 FrankHB. |
3 | 3 | |
4 | - This file is part of the YSLib project, and may only be used, | |
5 | - modified, and distributed under the terms of the YSLib project | |
6 | - license, LICENSE.TXT. By continuing to use, modify, or distribute | |
7 | - this file you indicate that you have read the license and | |
8 | - understand and accept it fully. | |
4 | + This file is part of the YSLib project, and may only be used, modified, | |
5 | + and distributed under the terms of the YSLib project license. | |
6 | + By continuing to use, modify, or distribute this file you indicate that | |
7 | + you have read the license and understand and accept it fully. | |
9 | 8 | */ |
10 | 9 | |
11 | 10 | /*! \file set.hpp |
12 | 11 | \ingroup YStandardEx |
13 | 12 | \brief 集合容器。 |
14 | -\version r2073 | |
13 | +\version r2084 | |
15 | 14 | \author FrankHB <frankhb1989@gmail.com> |
16 | 15 | \since build 665 |
17 | 16 | \par 创建时间: |
18 | 17 | 2016-01-23 20:13:53 +0800 |
19 | 18 | \par 修改时间: |
20 | - 2023-02-13 20:13 +0800 | |
19 | + 2024-04-10 22:42 +0800 | |
21 | 20 | \par 文本编码: |
22 | 21 | UTF-8 |
23 | 22 | \par 模块名称: |
@@ -622,9 +621,9 @@ | ||
622 | 621 | // away now (with %YB_Impl_Set_UseGenericLookup). |
623 | 622 | // XXX: G++ 5.2.0 rejects generic associative lookup in debug mode of %std::map. |
624 | 623 | // TODO: Find precise version supporting debug mode. |
625 | -#if ((__cpp_lib_generic_associative_lookup >= 201304L \ | |
626 | - || __cplusplus >= 201402L) && !(defined(__GLIBCXX__) \ | |
627 | - && defined(_GLIBCXX_DEBUG))) | |
624 | +#if (__cpp_lib_generic_associative_lookup >= 201304L \ | |
625 | + || __cplusplus >= 201402L) \ | |
626 | + && !(defined __GLIBCXX__ && defined _GLIBCXX_DEBUG) | |
628 | 627 | # define YB_Impl_MappedSet_UseGenericLookup true |
629 | 628 | #else |
630 | 629 | # define YB_Impl_MappedSet_UseGenericLookup false |
@@ -797,7 +796,6 @@ | ||
797 | 796 | \brief 允许指定不同于值类型的键的集合。 |
798 | 797 | \warning 若修改的值使键不等价,行为未定义。 |
799 | 798 | \sa mapped_set_traits |
800 | -\sa ystdex::try_emplace | |
801 | 799 | \see WG21 N3456 23.2.4 [associative.reqmts] 。 |
802 | 800 | \see Documentation::YBase @2.1.4.1 。 |
803 | 801 | \see Documentation::YBase @2.1.4.2 。 |
@@ -1205,9 +1203,9 @@ | ||
1205 | 1203 | |
1206 | 1204 | // XXX: The exception specification is changed. See the comment for the |
1207 | 1205 | // function %swap of %ystdex::map. |
1208 | - //! \since build 967 | |
1206 | + //! \since build 983 | |
1209 | 1207 | void |
1210 | - swap(mapped_set& s) ynoexcept_spec(is_nothrow_move_assignable<_fComp>()) | |
1208 | + swap(mapped_set& s) ynoexcept(is_nothrow_move_assignable<_fComp>()) | |
1211 | 1209 | { |
1212 | 1210 | m_map.swap(s.m_map); |
1213 | 1211 | } |
@@ -1,5 +1,5 @@ | ||
1 | 1 | /* |
2 | - © 2012-2023 FrankHB. | |
2 | + © 2012-2024 FrankHB. | |
3 | 3 | |
4 | 4 | This file is part of the YSLib project, and may only be used, modified, |
5 | 5 | and distributed under the terms of the YSLib project license. |
@@ -10,13 +10,13 @@ | ||
10 | 10 | /*! \file string.hpp |
11 | 11 | \ingroup YStandardEx |
12 | 12 | \brief ISO C++ 标准字符串扩展。 |
13 | -\version r4006 | |
13 | +\version r4160 | |
14 | 14 | \author FrankHB <frankhb1989@gmail.com> |
15 | 15 | \since build 304 |
16 | 16 | \par 创建时间: |
17 | 17 | 2012-04-26 20:12:19 +0800 |
18 | 18 | \par 修改时间: |
19 | - 2023-05-27 21:51 +0800 | |
19 | + 2024-04-18 22:25 +0800 | |
20 | 20 | \par 文本编码: |
21 | 21 | UTF-8 |
22 | 22 | \par 模块名称: |
@@ -28,18 +28,20 @@ | ||
28 | 28 | #define YB_INC_ystdex_string_hpp_ 1 |
29 | 29 | |
30 | 30 | #include "string_view.hpp" // for internal "string_view.hpp" (implying |
31 | -// "range.hpp" and "<libdefect/string.h>"), std::basic_string, | |
31 | +// "range.hpp" and <libdefect/string.h>), std::basic_string, | |
32 | 32 | // std::char_traits, or_, std::initializer_list, hash, std::hash, |
33 | 33 | // basic_string_view, is_fast_hash, false_, remove_cvref_t, std::declval, |
34 | 34 | // enable_if_inconvertible_t, enable_if_t, is_object, |
35 | 35 | // decay_t, true_, std::bidirectional_iterator_tag, is_class, is_equal, |
36 | -// is_same, std::to_string, is_enum; | |
36 | +// std::to_string, is_signed, is_arithmetic, is_integral, is_enum, is_same; | |
37 | 37 | #include "allocator.hpp" // for internal "allocator.hpp", std::allocator, |
38 | 38 | // allocator_traits, nested_allocator, yconstraint, yassume, |
39 | 39 | // ystdex::make_obj_using_allocator, YAssert; |
40 | 40 | #include "container.hpp" // for "container.hpp", enable_for_input_iterator_t, |
41 | 41 | // make_index_sequence, index_sequence, begin, end, empty, size, |
42 | 42 | // ystdex::sort_unique, ystdex::underlying; |
43 | +#include "charconv.h" // for "charconv.h", std::numeric_limits (with fixes), | |
44 | +// ystdex::write_decimal_integer; | |
43 | 45 | #include "cstring.h" // for ystdex::ntctslen, ystdex::is_null; |
44 | 46 | #include "array.hpp" // for to_array; |
45 | 47 | #include <istream> // for std::basic_istream; |
@@ -861,6 +863,18 @@ | ||
861 | 863 | {}; |
862 | 864 | |
863 | 865 | |
866 | +//! \since build 983 | |
867 | +namespace details | |
868 | +{ | |
869 | + | |
870 | +// XXX: Not using '__cpp_lib_string_resize_and_overwrite >= 202110L' because | |
871 | +// types other than %std::basic_string can also have such interface. | |
872 | +template<typename _type, typename... _tParams> | |
873 | +using mem_resize_and_overwrite_t = decltype(std::declval<_type&>() | |
874 | + .resize_and_overwrite(std::declval<_tParams>()...)); | |
875 | + | |
876 | +} // namespace details; | |
877 | + | |
864 | 878 | /*! |
865 | 879 | \ingroup traits |
866 | 880 | \brief 字符串特征。 |
@@ -885,6 +899,14 @@ | ||
885 | 899 | using pointer = value_type*; |
886 | 900 | using const_pointer = const value_type*; |
887 | 901 | using initializer = std::initializer_list<value_type>; |
902 | + /*! | |
903 | + \brief 具有兼容 ISO C++23 的成员 \c resize_and_overwrite 。 | |
904 | + \sa WG21 P1072R10 。 | |
905 | + \since build 983 | |
906 | + */ | |
907 | + using has_member_resize_and_overwrite | |
908 | + = is_detected_exact<void, details::mem_resize_and_overwrite_t, _tString, | |
909 | + size_type, size_type(&)(pointer, size_type)>; | |
888 | 910 | }; |
889 | 911 | |
890 | 912 |
@@ -2006,53 +2028,170 @@ | ||
2006 | 2028 | result_type, _tString>; |
2007 | 2029 | }; |
2008 | 2030 | |
2009 | -template<typename _type> | |
2010 | -using excluded_tostr | |
2011 | - = or_<is_same<_type, unsigned short>, is_same<_type, unsigned char>>; | |
2031 | +//! \since build 983 | |
2032 | +//!@{ | |
2033 | +template<class _tString, typename _type> | |
2034 | +void | |
2035 | +write_string_int(_tString& buf, _type val, false_) | |
2036 | +{ | |
2037 | + buf.resize(std::numeric_limits<_type>::digits10 + 2); | |
2012 | 2038 | |
2013 | -template<typename _type> | |
2014 | -YB_ATTR_nodiscard inline auto | |
2015 | -arithmetic_to_string(_type val, false_) -> decltype(std::to_string(val)) | |
2039 | + auto p(&buf[0]); | |
2040 | + | |
2041 | + if(val < 0) | |
2042 | + yunseq(*p++ = '-', val = -val); | |
2043 | + buf.resize(typename _tString::size_type(ystdex::write_decimal_integer(p, | |
2044 | + make_unsigned_t<_type>(val)) - &buf[0])); | |
2045 | +} | |
2046 | +template<class _tString, typename _type> | |
2047 | +void | |
2048 | +write_string_int(_tString& buf, _type val, true_) | |
2016 | 2049 | { |
2017 | - return std::to_string(val); | |
2050 | + buf.resize_and_overwrite(std::numeric_limits<_type>::digits10 + 2, | |
2051 | + [&] YB_LAMBDA_ANNOTATE((char* p, typename _tString::size_type), | |
2052 | + ynothrowv, nonnull(2)){ | |
2053 | + if(val < 0) | |
2054 | + yunseq(*p++ = '-', val = -val); | |
2055 | + return typename _tString::size_type(ystdex::write_decimal_integer(p, | |
2056 | + make_unsigned_t<_type>(val)) - &buf[0]); | |
2057 | + }); | |
2018 | 2058 | } |
2019 | -YB_ATTR_nodiscard inline string | |
2020 | -arithmetic_to_string(unsigned val, true_) | |
2059 | +template<class _tString, typename _type> | |
2060 | +void | |
2061 | +write_string_int(_tString& buf, _type val) | |
2021 | 2062 | { |
2022 | - return std::to_string(val); | |
2063 | + details::write_string_int(buf, val, | |
2064 | + typename string_traits<_tString>::has_member_resize_and_overwrite()); | |
2023 | 2065 | } |
2024 | 2066 | |
2025 | -template<typename _type> | |
2026 | -YB_ATTR_nodiscard inline auto | |
2027 | -arithmetic_to_wstring(_type val, false_) -> decltype(std::to_wstring(val)) | |
2067 | +template<class _tString, typename _type> | |
2068 | +void | |
2069 | +write_string_uint(_tString& buf, _type val, false_) | |
2028 | 2070 | { |
2029 | - return std::to_wstring(val); | |
2071 | + buf.resize(std::numeric_limits<_type>::digits10 + 1); | |
2072 | + buf.resize(typename _tString::size_type( | |
2073 | + ystdex::write_decimal_integer(&buf[0], val) - &buf[0])); | |
2030 | 2074 | } |
2031 | -YB_ATTR_nodiscard inline wstring | |
2032 | -arithmetic_to_wstring(unsigned val, true_) | |
2075 | +template<class _tString, typename _type> | |
2076 | +void | |
2077 | +write_string_uint(_tString& buf, _type val, true_) | |
2033 | 2078 | { |
2034 | - return std::to_wstring(val); | |
2079 | + buf.resize_and_overwrite(std::numeric_limits<_type>::digits10 + 1, | |
2080 | + [&] YB_LAMBDA_ANNOTATE((char* p, typename _tString::size_type), | |
2081 | + ynothrowv, nonnull(2)){ | |
2082 | + return typename | |
2083 | + _tString::size_type(ystdex::write_decimal_integer(p, val) - p); | |
2084 | + }); | |
2035 | 2085 | } |
2086 | +template<class _tString, typename _type> | |
2087 | +void | |
2088 | +write_string_uint(_tString& buf, _type val) | |
2089 | +{ | |
2090 | + details::write_string_uint(buf, val, | |
2091 | + typename string_traits<_tString>::has_member_resize_and_overwrite()); | |
2092 | +} | |
2093 | + | |
2094 | +template<class _tString, typename _type, typename... _tParams> | |
2095 | +YB_ATTR_nodiscard YB_PURE inline _tString | |
2096 | +integral_to_string(_type val, false_, _tParams&&... args) | |
2097 | +{ | |
2098 | + _tString buf(yforward(args)...); | |
2099 | + | |
2100 | + details::write_string_uint(buf, val); | |
2101 | + return buf; | |
2102 | +} | |
2103 | +template<class _tString, typename _type, typename... _tParams> | |
2104 | +YB_ATTR_nodiscard YB_PURE inline _tString | |
2105 | +integral_to_string(_type val, true_, _tParams&&... args) | |
2106 | +{ | |
2107 | + _tString buf(yforward(args)...); | |
2108 | + | |
2109 | + details::write_string_int(buf, val); | |
2110 | + return buf; | |
2111 | +} | |
2112 | + | |
2113 | +template<class _tString, typename _type> | |
2114 | +YB_ATTR_nodiscard inline auto | |
2115 | +arithmetic_to_string(_type val, false_) | |
2116 | + -> decltype(_tString(std::to_string(val))) | |
2117 | +{ | |
2118 | + return _tString(std::to_string(val)); | |
2119 | +} | |
2120 | +template<class _tString, typename _type, class _tAlloc> | |
2121 | +YB_ATTR_nodiscard inline auto | |
2122 | +arithmetic_to_string(_type val, false_, const _tAlloc& a) | |
2123 | + -> decltype(_tString(std::to_string(val), a)) | |
2124 | +{ | |
2125 | + return _tString(std::to_string(val), a); | |
2126 | +} | |
2127 | +template<class _tString, typename _type> | |
2128 | +YB_ATTR_nodiscard YB_PURE inline _tString | |
2129 | +arithmetic_to_string(_type val, true_) | |
2130 | +{ | |
2131 | + return details::integral_to_string<_tString>(val, is_signed<_type>()); | |
2132 | +} | |
2133 | +template<class _tString, typename _type, class _tAlloc> | |
2134 | +YB_ATTR_nodiscard YB_PURE inline _tString | |
2135 | +arithmetic_to_string(_type val, true_, const _tAlloc& a) | |
2136 | +{ | |
2137 | + return details::integral_to_string<_tString>(val, is_signed<_type>(), a); | |
2138 | +} | |
2139 | + | |
2140 | +template<class _tString, typename _type> | |
2141 | +YB_ATTR_nodiscard inline auto | |
2142 | +arithmetic_to_wstring(_type val, false_) | |
2143 | + -> decltype(_tString(std::to_wstring(val))) | |
2144 | +{ | |
2145 | + return _tString(std::to_wstring(val)); | |
2146 | +} | |
2147 | +template<class _tString, typename _type, class _tAlloc> | |
2148 | +YB_ATTR_nodiscard inline auto | |
2149 | +arithmetic_to_wstring(_type val, false_, const _tAlloc& a) | |
2150 | + -> decltype(std::to_wstring(val)) | |
2151 | +{ | |
2152 | + return _tString(std::to_wstring(val), a); | |
2153 | +} | |
2154 | +template<class _tString, typename _type> | |
2155 | +YB_ATTR_nodiscard YB_PURE inline _tString | |
2156 | +arithmetic_to_wstring(_type val, true_) | |
2157 | +{ | |
2158 | + return details::integral_to_string<_tString>(val, is_signed<_type>()); | |
2159 | +} | |
2160 | +template<class _tString, typename _type, class _tAlloc> | |
2161 | +YB_ATTR_nodiscard YB_PURE inline _tString | |
2162 | +arithmetic_to_wstring(_type val, true_, const _tAlloc& a) | |
2163 | +{ | |
2164 | + return details::integral_to_string<_tString>(val, is_signed<_type>(), a); | |
2165 | +} | |
2166 | +//!@} | |
2036 | 2167 | |
2037 | 2168 | } // namespace details; |
2038 | 2169 | |
2039 | 2170 | /*! |
2040 | 2171 | \brief 转换为字符串:basic_string 的实例对象。 |
2041 | -\note 可与标准库的同名函数共用以避免某些类型转换警告,如 G++ 的 [-Wsign-promo] 。 | |
2172 | +\sa WG21 P1072R10 。 | |
2042 | 2173 | \since build 928 |
2174 | + | |
2175 | +和标准库不同,可通过第一模板参数指定字符串,并可选通过结尾的函数参数支持分配器。 | |
2176 | +指定的字符串应和 \c std::basic_string 兼容,即任意接口若存在, | |
2177 | + 其行为和 \c std::basic_string 一致。 | |
2178 | +特定版本的 \c std::basic_string 可被自动检查并依赖: | |
2179 | + \li \c 成员 overwrite_for_resize 。 | |
2180 | +可与标准库的同名函数共用以避免某些类型转换警告,如 G++ 的 [-Wsign-promo] 。 | |
2043 | 2181 | */ |
2044 | 2182 | //!@{ |
2045 | 2183 | template<class _tString = string, typename _type> |
2046 | 2184 | YB_ATTR_nodiscard inline yimpl(enable_if_t)<is_arithmetic<_type>{}, _tString> |
2047 | 2185 | to_string(_type val) |
2048 | 2186 | { |
2049 | - return details::arithmetic_to_string(val, details::excluded_tostr<_type>()); | |
2187 | + return details::arithmetic_to_string<_tString>(val, is_integral<_type>()); | |
2050 | 2188 | } |
2051 | 2189 | template<class _tString = string, typename _type> |
2052 | 2190 | YB_ATTR_nodiscard inline yimpl(enable_if_t)<is_arithmetic<_type>{}, _tString> |
2053 | 2191 | to_string(_type val, typename _tString::allocator_type a) |
2054 | 2192 | { |
2055 | - return _tString(ystdex::to_string(val), a); | |
2193 | + return | |
2194 | + details::arithmetic_to_string<_tString>(val, is_integral<_type>(), a); | |
2056 | 2195 | } |
2057 | 2196 | template<class _tString = string, typename _type> |
2058 | 2197 | YB_ATTR_nodiscard inline yimpl(enable_if_t)<is_enum<_type>{}, _tString> |
@@ -2102,13 +2241,14 @@ | ||
2102 | 2241 | YB_ATTR_nodiscard inline yimpl(enable_if_t)<is_arithmetic<_type>{}, _tString> |
2103 | 2242 | to_wstring(_type val) |
2104 | 2243 | { |
2105 | - return details::arithmetic_to_wstring(val, details::excluded_tostr<_type>()); | |
2244 | + return details::arithmetic_to_wstring<_tString>(val, is_integral<_type>()); | |
2106 | 2245 | } |
2107 | 2246 | template<class _tString = wstring, typename _type> |
2108 | 2247 | YB_ATTR_nodiscard inline yimpl(enable_if_t)<is_arithmetic<_type>{}, _tString> |
2109 | 2248 | to_wstring(_type val, typename _tString::allocator_type a) |
2110 | 2249 | { |
2111 | - return _tString(ystdex::to_wstring(val), a); | |
2250 | + return | |
2251 | + details::arithmetic_to_wstring<_tString>(val, is_integral<_type>(), a); | |
2112 | 2252 | } |
2113 | 2253 | template<class _tString = wstring, typename _type> |
2114 | 2254 | YB_ATTR_nodiscard inline yimpl(enable_if_t)<is_enum<_type>{}, _tString> |
@@ -1,5 +1,5 @@ | ||
1 | 1 | /* |
2 | - © 2011-2013, 2016, 2018-2019, 2021-2023 FrankHB. | |
2 | + © 2011-2013, 2016, 2018-2019, 2021-2024 FrankHB. | |
3 | 3 | |
4 | 4 | This file is part of the YSLib project, and may only be used, modified, |
5 | 5 | and distributed under the terms of the YSLib project license. |
@@ -10,13 +10,13 @@ | ||
10 | 10 | /*! \file type_inspection.hpp |
11 | 11 | \ingroup YStandardEx |
12 | 12 | \brief 类型检查元编程设施。 |
13 | -\version r2050 | |
13 | +\version r2576 | |
14 | 14 | \author FrankHB <frankhb1989@gmail.com> |
15 | 15 | \since build 832 |
16 | 16 | \par 创建时间: |
17 | 17 | 2018-07-23 17:54:58 +0800 |
18 | 18 | \par 修改时间: |
19 | - 2023-09-13 05:45 +0800 | |
19 | + 2024-04-04 21:51 +0800 | |
20 | 20 | \par 文本编码: |
21 | 21 | UTF-8 |
22 | 22 | \par 模块名称: |
@@ -28,8 +28,11 @@ | ||
28 | 28 | #define YB_INC_ystdex_type_inspection_hpp_ 1 |
29 | 29 | |
30 | 30 | #include "integral_constant.hpp" // for "integral_constant.hpp", <type_traits>, |
31 | -// __cpp_lib_is_null_pointer, __cpp_lib_is_final, std::remove_cv_t, nullptr_t, | |
32 | -// bool_, __has_extension, false_; | |
31 | +// __cpp_lib_is_null_pointer, __cpp_lib_is_final, std::remove_cv, nullptr_t, | |
32 | +// bool_, __has_extension, false_, YB_Use_int128, or_, int128_t, uint128_t, | |
33 | +// and_, not_, std::add_const, std::remove_reference, std::remove_pointer, | |
34 | +// true_, nor_, size_t_, std::add_cv; | |
35 | +#include <climits> // for CHAR_BIT; | |
33 | 36 | |
34 | 37 | /*! |
35 | 38 | \brief \c \<type_traits> 特性测试宏。 |
@@ -58,6 +61,7 @@ | ||
58 | 61 | /*! \defgroup type_traits_operations Type Traits Operations |
59 | 62 | \ingroup metafunctions traits |
60 | 63 | \brief 类型特征操作。 |
64 | +\note 同 [meta.rqmts] ,除非另行指定,允许不完整类型作为模板参数的特定使用。 | |
61 | 65 | \since build 306 |
62 | 66 | */ |
63 | 67 |
@@ -84,6 +88,15 @@ | ||
84 | 88 | |
85 | 89 | |
86 | 90 | /*! |
91 | +\ingroup metafunctions | |
92 | +\brief 嵌套类型别名。 | |
93 | +\since build 649 | |
94 | +*/ | |
95 | +template<class _type> | |
96 | +using _t = typename _type::type; | |
97 | + | |
98 | + | |
99 | +/*! | |
87 | 100 | \brief 包含 ISO C++ 2011 引入的名称的命名空间。 |
88 | 101 | \since build 607 |
89 | 102 | */ |
@@ -91,9 +104,80 @@ | ||
91 | 104 | { |
92 | 105 | |
93 | 106 | //! \since build 245 |
107 | +using std::is_void; | |
108 | + | |
109 | +} // inline namespace cpp2011; | |
110 | + | |
111 | +/*! | |
112 | +\brief 包含 ISO C++ 2014 引入的名称的命名空间。 | |
113 | +\since build 607 | |
114 | +*/ | |
115 | +inline namespace cpp2014 | |
116 | +{ | |
117 | + | |
118 | +/*! | |
119 | +\see LWG 2247 。 | |
120 | +\since build 832 | |
121 | +*/ | |
94 | 122 | //!@{ |
95 | -using std::is_void; | |
123 | +#if __cpp_lib_is_null_pointer >= 201309L | |
124 | +using std::is_null_pointer; | |
125 | +#else | |
126 | +//! \ingroup YBase_replacement_features unary_type_traits | |
127 | +template<typename _type> | |
128 | +struct is_null_pointer : std::is_same<_t<std::remove_cv<_type>>, nullptr_t> | |
129 | +{}; | |
130 | +#endif | |
131 | +//!@} | |
132 | +} // inline namespace cpp2014; | |
133 | + | |
134 | +inline namespace cpp2011 | |
135 | +{ | |
136 | + | |
137 | +// NOTE: See $2024-03 @ %Documentation::Workflow. | |
138 | +#if YB_Use_int128 > 0 && ((defined __GLIBCXX__ && defined __STRICT_ANSI__) \ | |
139 | + || (defined _LIBCPP_VERSION && _LIBCPP_VERSION <= 1101)) | |
140 | +# define YB_Impl_ext_int128 true | |
141 | +#else | |
142 | +# define YB_Impl_ext_int128 false | |
143 | +#endif | |
144 | + | |
145 | +#if !YB_HAS_BUILTIN_NULLPTR || YB_Impl_ext_int128 | |
146 | +# define YB_Impl_TypeInspection_ut_primary(_n) \ | |
147 | + template<typename _type> \ | |
148 | + struct _n : std::_n<_type> \ | |
149 | + {}; | |
150 | +#endif | |
151 | + | |
152 | +#if YB_Impl_ext_int128 | |
153 | +# define YB_Impl_TypeInspection_ut_spec(_n, _t) \ | |
154 | + template<> \ | |
155 | + struct _n<_t> : true_ \ | |
156 | + {}; | |
157 | +# define YB_Impl_TypeInspection_ut_specs(_n, _t) \ | |
158 | + YB_Impl_TypeInspection_ut_spec(_n, _t) \ | |
159 | + YB_Impl_TypeInspection_ut_spec(_n, const _t) \ | |
160 | + YB_Impl_TypeInspection_ut_spec(_n, volatile _t) \ | |
161 | + YB_Impl_TypeInspection_ut_spec(_n, const volatile _t) | |
162 | +# define YB_Impl_TypeInspection_ut_ext_int128(_n) \ | |
163 | + YB_Impl_TypeInspection_ut_primary(_n) \ | |
164 | + YB_Impl_TypeInspection_ut_specs(_n, int128_t) \ | |
165 | + YB_Impl_TypeInspection_ut_specs(_n, uint128_t) | |
166 | +#endif | |
167 | + | |
168 | +//! \since build 245 | |
169 | +//!@{ | |
170 | +#if YB_Impl_ext_int128 | |
171 | +/*! | |
172 | +\ingroup YBase_replacement_features unary_type_traits | |
173 | +\since build 983 | |
174 | +*/ | |
175 | +//!@{ | |
176 | +YB_Impl_TypeInspection_ut_ext_int128(is_integral) | |
177 | +//!@} | |
178 | +#else | |
96 | 179 | using std::is_integral; |
180 | +#endif | |
97 | 181 | using std::is_floating_point; |
98 | 182 | using std::is_array; |
99 | 183 | using std::is_pointer; |
@@ -102,31 +186,122 @@ | ||
102 | 186 | using std::is_member_object_pointer; |
103 | 187 | using std::is_member_function_pointer; |
104 | 188 | using std::is_enum; |
189 | +#if YB_HAS_BUILTIN_NULLPTR | |
105 | 190 | using std::is_class; |
191 | +#else | |
192 | +/*! | |
193 | +\ingroup YBase_replacement_features unary_type_traits | |
194 | +\since build 983 | |
195 | +*/ | |
196 | +template<typename _type> | |
197 | +struct is_class : and_<std::is_class<_type>, not_<is_null_pointer<_type>>> | |
198 | +{}; | |
199 | +#endif | |
106 | 200 | using std::is_union; |
107 | 201 | using std::is_function; |
108 | 202 | |
109 | 203 | using std::is_reference; |
204 | +#if YB_Impl_ext_int128 | |
205 | +/*! | |
206 | +\ingroup YBase_replacement_features unary_type_traits | |
207 | +\since build 983 | |
208 | +*/ | |
209 | +//!@{ | |
210 | +YB_Impl_TypeInspection_ut_ext_int128(is_arithmetic) | |
211 | +//!@} | |
212 | +#else | |
110 | 213 | using std::is_arithmetic; |
214 | +#endif | |
215 | +#if !YB_HAS_BUILTIN_NULLPTR || YB_Impl_ext_int128 | |
216 | +/*! | |
217 | +\ingroup YBase_replacement_features unary_type_traits | |
218 | +\since build 983 | |
219 | +*/ | |
220 | +//!@{ | |
221 | +YB_Impl_TypeInspection_ut_ext_int128(is_fundamental) | |
222 | +//!@} | |
223 | +#else | |
111 | 224 | using std::is_fundamental; |
225 | +#endif | |
112 | 226 | using std::is_object; |
227 | +#if !YB_HAS_BUILTIN_NULLPTR || YB_Impl_ext_int128 | |
228 | +/*! | |
229 | +\ingroup YBase_replacement_features unary_type_traits | |
230 | +\since build 983 | |
231 | +*/ | |
232 | +//!@{ | |
233 | +# if YB_HAS_BUILTIN_NULLPTR | |
234 | +YB_Impl_TypeInspection_ut_primary(is_scalar) | |
235 | + | |
236 | +YB_Impl_TypeInspection_ut_primary(is_compound) | |
237 | +# else | |
238 | +template<typename _type> | |
239 | +struct is_scalar : or_<std::is_scalar<_type>, is_null_pointer<_type>> | |
240 | +{}; | |
241 | + | |
242 | +template<typename _type> | |
243 | +struct is_compound : or_<std::is_compound<_type>, not_<is_null_pointer<_type>>> | |
244 | +{}; | |
245 | +# endif | |
246 | + | |
247 | +# if YB_Impl_ext_int128 | |
248 | +YB_Impl_TypeInspection_ut_specs(is_scalar, int128_t) | |
249 | +YB_Impl_TypeInspection_ut_specs(is_scalar, uint128_t) | |
250 | + | |
251 | +YB_Impl_TypeInspection_ut_specs(is_compound, int128_t) | |
252 | +YB_Impl_TypeInspection_ut_specs(is_compound, uint128_t) | |
253 | +# endif | |
254 | +//!@} | |
255 | +#else | |
113 | 256 | using std::is_scalar; |
114 | 257 | using std::is_compound; |
258 | +#endif | |
115 | 259 | using std::is_member_pointer; |
116 | 260 | |
117 | 261 | using std::is_const; |
118 | 262 | using std::is_volatile; |
119 | 263 | using std::is_trivial; |
120 | -// using std::is_trivially_copyable; | |
264 | +/*! | |
265 | +\since build 983 | |
266 | +\see CWG 1734 。 | |
267 | +*/ | |
268 | +// NOTE: It is unspecified whether the resolution of CWG 1734 is applied. See | |
269 | +// also $2024-03 @ %Documentation::Workflow. | |
270 | +using std::is_trivially_copyable; | |
121 | 271 | using std::is_standard_layout; |
122 | 272 | using std::is_empty; |
123 | 273 | using std::is_polymorphic; |
124 | 274 | using std::is_abstract; |
125 | 275 | |
276 | +#if YB_Impl_ext_int128 | |
277 | +/*! | |
278 | +\ingroup YBase_replacement_features unary_type_traits | |
279 | +\since build 983 | |
280 | +*/ | |
281 | +//!@{ | |
282 | +YB_Impl_TypeInspection_ut_primary(is_signed) | |
283 | +YB_Impl_TypeInspection_ut_specs(is_signed, int128_t) | |
284 | + | |
285 | +YB_Impl_TypeInspection_ut_primary(is_unsigned) | |
286 | +YB_Impl_TypeInspection_ut_specs(is_unsigned, uint128_t) | |
287 | +//!@} | |
288 | +#else | |
126 | 289 | using std::is_signed; |
127 | 290 | using std::is_unsigned; |
291 | +#endif | |
292 | + | |
293 | +#if YB_Impl_ext_int128 | |
294 | +# undef YB_Impl_TypeInspection_ut_ext_int128 | |
295 | +# undef YB_Impl_TypeInspection_ut_specs | |
296 | +# undef YB_Impl_TypeInspection_ut_spec | |
297 | +#endif | |
298 | + | |
299 | +#if !YB_HAS_BUILTIN_NULLPTR || YB_Impl_ext_int128 | |
300 | +# undef YB_Impl_TypeInspection_ut_primary | |
301 | +#endif | |
128 | 302 | |
129 | 303 | using std::is_constructible; |
304 | +//!@} | |
130 | 305 | //! \since build 551 |
131 | 306 | //!@{ |
132 | 307 | using std::is_default_constructible; |
@@ -168,6 +343,8 @@ | ||
168 | 343 | using std::is_nothrow_destructible; |
169 | 344 | //!@} |
170 | 345 | |
346 | +//! \since build 245 | |
347 | +//!@{ | |
171 | 348 | using std::has_virtual_destructor; |
172 | 349 | |
173 | 350 | using std::alignment_of; |
@@ -181,30 +358,8 @@ | ||
181 | 358 | |
182 | 359 | } // inline namespace cpp2011; |
183 | 360 | |
184 | - | |
185 | -/*! | |
186 | -\brief 包含 ISO C++ 2014 引入的名称的命名空间。 | |
187 | -\since build 607 | |
188 | -*/ | |
189 | 361 | inline namespace cpp2014 |
190 | 362 | { |
191 | - | |
192 | -/*! | |
193 | -\see LWG 2247 。 | |
194 | -\since build 832 | |
195 | -*/ | |
196 | -//!@{ | |
197 | -#if __cpp_lib_is_null_pointer >= 201309L | |
198 | -using std::is_null_pointer; | |
199 | -#else | |
200 | -//! \ingroup YBase_replacement_features unary_type_traits | |
201 | -template<typename _type> | |
202 | -struct is_null_pointer | |
203 | - : is_same<typename std::remove_cv<_type>::type, nullptr_t> | |
204 | -{}; | |
205 | -#endif | |
206 | -//!@} | |
207 | - | |
208 | 363 | /*! |
209 | 364 | \see LWG 2112 。 |
210 | 365 | \since build 938 |
@@ -236,6 +391,459 @@ | ||
236 | 391 | //!@} |
237 | 392 | |
238 | 393 | } // inline namespace cpp2014; |
394 | + | |
395 | + | |
396 | +/*! | |
397 | +\ingroup unary_type_traits | |
398 | +\tparam _type 需要判断特征的类型参数。 | |
399 | +*/ | |
400 | +//!@{ | |
401 | +//! \note 以下参数可能是 cv 修饰的类型,结果和去除 cv 修饰符的类型一致。 | |
402 | +//!@{ | |
403 | +/*! | |
404 | +\brief 判断指定类型是否为扩展整数:不属于标准整数类型但视为整数处理的对象类型。 | |
405 | +\since build 983 | |
406 | +*/ | |
407 | +template<typename _type> | |
408 | +struct is_extended_integer | |
409 | +#if YB_Use_int128 > 0 | |
410 | + : or_<is_same<_t<std::remove_cv<_type>>, int128_t>, | |
411 | + is_same<_t<std::remove_cv<_type>>, uint128_t>> | |
412 | +#else | |
413 | + : false_ | |
414 | +#endif | |
415 | +{}; | |
416 | + | |
417 | + | |
418 | +/*! | |
419 | +\brief 判断是否为未知大小的数组类型。 | |
420 | +\since build 651 | |
421 | +*/ | |
422 | +template<typename _type> | |
423 | +struct is_array_of_unknown_bound | |
424 | + : bool_<is_array<_type>() && extent<_type>() == 0> | |
425 | +{}; | |
426 | + | |
427 | + | |
428 | +/*! | |
429 | +\brief 判断指定类型是否为非 \c cv 限定对象的数组类型。 | |
430 | +\since build 972 | |
431 | +*/ | |
432 | +template<typename> | |
433 | +struct is_array_of_unqualified_object; | |
434 | + | |
435 | + | |
436 | +/*! | |
437 | +\brief 判断指定类型是否为可被继承的类类型。 | |
438 | +\since build 940 | |
439 | +*/ | |
440 | +template<typename _type> | |
441 | +struct is_inheritable_class : and_<is_class<_type>, not_<is_final<_type>>> | |
442 | +{}; | |
443 | + | |
444 | + | |
445 | +/*! | |
446 | +\brief 判断指定类型是否为非 const 对象类型。 | |
447 | +\since build 650 | |
448 | +*/ | |
449 | +template<typename _type> | |
450 | +struct is_nonconst_object | |
451 | + : and_<is_object<_type>, is_same<_t<std::add_const<_type>>, _type>> | |
452 | +{}; | |
453 | + | |
454 | + | |
455 | +//! \since build 333 | |
456 | +//!@{ | |
457 | +//! \brief 判断指定类型是否为类类型左值引用。 | |
458 | +template<typename _type> | |
459 | +struct is_lvalue_class_reference : and_<is_lvalue_reference<_type>, | |
460 | + is_class<_t<std::remove_reference<_type>>>> | |
461 | +{}; | |
462 | + | |
463 | + | |
464 | +//! \brief 判断指定类型是否为类类型右值引用。 | |
465 | +template<typename _type> | |
466 | +struct is_rvalue_class_reference : and_<is_rvalue_reference<_type>, | |
467 | + is_class<_t<std::remove_pointer<_type>>>> | |
468 | +{}; | |
469 | + | |
470 | + | |
471 | +//! \brief 判断指定类型是否为指向类类型的指针。 | |
472 | +template<typename _type> | |
473 | +struct is_class_pointer | |
474 | + : and_<is_pointer<_type>, is_class<_t<std::remove_pointer<_type>>>> | |
475 | +{}; | |
476 | +//!@} | |
477 | + | |
478 | + | |
479 | +//! \since build 630 | |
480 | +//!@{ | |
481 | +//! \brief 判断指定类型是否为指向函数类型的指针。 | |
482 | +template<typename _type> | |
483 | +struct is_function_pointer | |
484 | + : and_<is_pointer<_type>, is_function<_t<std::remove_pointer<_type>>>> | |
485 | +{}; | |
486 | + | |
487 | + | |
488 | +//! \brief 判断指定类型是否为对象或 void 类型。 | |
489 | +template<typename _type> | |
490 | +struct is_object_or_void : or_<is_object<_type>, is_void<_type>> | |
491 | +{}; | |
492 | + | |
493 | + | |
494 | +//! \brief 判断指定类型是否为指向对象或空类型的指针。 | |
495 | +template<typename _type> | |
496 | +struct is_object_pointer | |
497 | + : and_<is_pointer<_type>, is_object_or_void<_t<std::remove_pointer<_type>>>> | |
498 | +{}; | |
499 | + | |
500 | + | |
501 | +//! \brief 判断指定类型是否为指向对象类型的指针。 | |
502 | +template<typename _type> | |
503 | +struct is_pointer_to_object | |
504 | + : and_<is_pointer<_type>, is_object<_t<std::remove_pointer<_type>>>> | |
505 | +{}; | |
506 | +//!@} | |
507 | + | |
508 | + | |
509 | +/*! | |
510 | +\brief 判断指定类型是否为类类型。 | |
511 | +\since build 588 | |
512 | +*/ | |
513 | +template<typename _type> | |
514 | +struct is_class_type | |
515 | + : or_<is_class<_type>, is_union<_type>> | |
516 | +{}; | |
517 | + | |
518 | + | |
519 | +//! \since build 694 | |
520 | +namespace details | |
521 | +{ | |
522 | + | |
523 | +template<typename _type> | |
524 | +struct is_referenceable_function : false_ | |
525 | +{}; | |
526 | + | |
527 | +template<typename _tRes, typename... _tParams ynoexcept_param(ne)> | |
528 | +struct is_referenceable_function<_tRes(_tParams...) ynoexcept_qual(ne)> : true_ | |
529 | +{}; | |
530 | + | |
531 | +template<typename _tRes, typename... _tParams ynoexcept_param(ne)> | |
532 | +struct is_referenceable_function<_tRes(_tParams..., ...) ynoexcept_qual(ne)> | |
533 | + : true_ | |
534 | +{}; | |
535 | + | |
536 | + | |
537 | +//! \since build 867 | |
538 | +//!@{ | |
539 | +template<typename _type1, typename _type2, bool = is_same<_type1, _type2>{}> | |
540 | +struct is_same_or_convertible : is_convertible<_type1, _type2> | |
541 | +{}; | |
542 | + | |
543 | +template<typename _type1, typename _type2> | |
544 | +struct is_same_or_convertible<_type1, _type2, true> : true_ | |
545 | +{}; | |
546 | +//!@} | |
547 | + | |
548 | +} // namespace details; | |
549 | + | |
550 | +/*! | |
551 | +\brief 判断指定类型是否为可引用类型。 | |
552 | +\see ISO C++11 17.3.20 [defns.referenceable] 。 | |
553 | +\since build 694 | |
554 | +*/ | |
555 | +template<typename _type> | |
556 | +struct is_referenceable : or_<is_object<_type>, is_reference<_type>, | |
557 | + details::is_referenceable_function<_type>> | |
558 | +{}; | |
559 | + | |
560 | + | |
561 | +/*! | |
562 | +\brief 判断指定类型是否可作为返回类型。 | |
563 | +\pre 类型参数满足同 ISO C++ 对 is_abstract 的要求。 | |
564 | +\note 即排除数组类型、抽象类类型和函数类型的所有类型。 | |
565 | +\see ISO C++11 8.3.5/8 和 ISO C++11 10.4/3 。 | |
566 | +\since build 333 | |
567 | + | |
568 | +对类型参数的具体要求如下: | |
569 | +若类型参数是一个非联合体的类类型,类型参数是完整类型。 | |
570 | +*/ | |
571 | +template<typename _type> | |
572 | +struct is_returnable | |
573 | + : nor_<is_array<_type>, is_abstract<_type>, is_function<_type>> | |
574 | +{}; | |
575 | + | |
576 | + | |
577 | +/*! | |
578 | +\pre remove_all_extents\<_type> 是完整类型或(可能 cv 修饰的) \c void 。 | |
579 | +\see ISO C++17 [class.prop]/2 。 | |
580 | +\since build 853 | |
581 | +*/ | |
582 | +//!@{ | |
583 | +/*! | |
584 | +\brief 判断指定类型是否为平凡的非联合类类型。 | |
585 | +\note 注意和 ISO C++ 的 \c std::is_class 类似,排除联合。 | |
586 | +*/ | |
587 | +template<typename _type> | |
588 | +struct is_trivial_class : and_<is_trivial<_type>, is_class<_type>> | |
589 | +{}; | |
590 | + | |
591 | +template<typename _type> | |
592 | +struct is_trivial_class_type : and_<is_trivial<_type>, is_class_type<_type>> | |
593 | +{}; | |
594 | + | |
595 | +//! \brief 判断指定类型是否为平凡的联合类型。 | |
596 | +template<typename _type> | |
597 | +struct is_trivial_union : and_<is_trivial<_type>, is_union<_type>> | |
598 | +{}; | |
599 | +//!@} | |
600 | +//!@} | |
601 | + | |
602 | + | |
603 | +/*! | |
604 | +\brief 判断指定类型是否为 \c const 或 \c volatile 类型。 | |
605 | +\since build 590 | |
606 | +*/ | |
607 | +template<typename _type> | |
608 | +struct is_cv : or_<is_const<_type>, is_volatile<_type>> | |
609 | +{}; | |
610 | + | |
611 | + | |
612 | +/*! | |
613 | +\brief 判断指定类型是否已退化为指定类型。 | |
614 | +\since build 841 | |
615 | +*/ | |
616 | +template<typename _type, typename _tTo = _type> | |
617 | +struct is_decayed : is_same<_type, _t<std::decay<_tTo>>> | |
618 | +{}; | |
619 | + | |
620 | + | |
621 | +/*! | |
622 | +\brief 判断指定类型是否可分解为一个参数为类型的模板和类型参数。 | |
623 | +\since build 683 | |
624 | +*/ | |
625 | +//!@{ | |
626 | +template<typename> | |
627 | +struct is_decomposable : false_ | |
628 | +{}; | |
629 | + | |
630 | +template<template<typename...> class _gOp, typename... _types> | |
631 | +struct is_decomposable<_gOp<_types...>> : true_ | |
632 | +{}; | |
633 | +//!@} | |
634 | + | |
635 | + | |
636 | +/*! | |
637 | +\brief 判断指定类型是否为非限定的指定类型。 | |
638 | +\since build 865 | |
639 | +*/ | |
640 | +template<typename _type, typename _tTo = _type> | |
641 | +struct is_unqualified : is_same<_type, _t<std::remove_cv<_tTo>>> | |
642 | +{}; | |
643 | + | |
644 | + | |
645 | +/*! | |
646 | +\brief 判断指定类型是否为非 \c cv 限定对象类型。 | |
647 | +\since build 867 | |
648 | +*/ | |
649 | +template<typename _type> | |
650 | +struct is_unqualified_object : and_<is_object<_type>, is_unqualified<_type>> | |
651 | +{}; | |
652 | + | |
653 | + | |
654 | +template<typename _type> | |
655 | +struct is_array_of_unqualified_object : and_<is_array<_type>, | |
656 | + is_unqualified_object<_t<std::remove_extent<_type>>>> | |
657 | +{}; | |
658 | + | |
659 | + | |
660 | +/*! | |
661 | +\pre 类型参数满足同 ISO C++ \c is_trivial 参数的要求。 | |
662 | +\see LWG 2116 。 | |
663 | +\see LWG 2827 。 | |
664 | +\see WG21 P2842R0 。 | |
665 | +\since build 630 | |
666 | + | |
667 | +对类型参数 \c _type ,具体的要求是 remove_all_extents\<_type> 满足以下之一: | |
668 | + 完整类型。 | |
669 | + (可能 cv 修饰的) \c void 。 | |
670 | + 未知大小的数组。 | |
671 | +当前对 WG21 P2842R0 中立,即是否要求平凡或无异常析构未指定。 | |
672 | +按 WG21 P2842R0 建议的现行 ISO C++ 规则,一般仅要求可访问的析构函数存在。 | |
673 | +*/ | |
674 | +//!@{ | |
675 | +template<typename _type> | |
676 | +struct is_copyable | |
677 | + : and_<is_copy_constructible<_type>, is_copy_assignable<_type>> | |
678 | +{}; | |
679 | + | |
680 | + | |
681 | +//! \since build 983 | |
682 | +template<typename _type> | |
683 | +struct is_movable | |
684 | + : and_<is_move_constructible<_type>, is_move_assignable<_type>> | |
685 | +{}; | |
686 | + | |
687 | + | |
688 | +template<typename _type> | |
689 | +struct is_nothrow_copyable : and_<is_nothrow_copy_constructible<_type>, | |
690 | + is_nothrow_copy_assignable<_type>> | |
691 | +{}; | |
692 | + | |
693 | + | |
694 | +//! \since build 983 | |
695 | +template<typename _type> | |
696 | +struct is_nothrow_movable : and_<is_nothrow_move_constructible<_type>, | |
697 | + is_nothrow_move_assignable<_type>> | |
698 | +{}; | |
699 | + | |
700 | + | |
701 | +/*! | |
702 | +\brief 判断指定类型是否为可复制构造但不可无抛出异常地转移构造的类型。 | |
703 | +\note 和 std::move_if_noexcept 需要选择复制的条件相同。 | |
704 | +\since build 865 | |
705 | +*/ | |
706 | +template<typename _type> | |
707 | +struct is_throwing_move_copyable : and_<is_copy_constructible<_type>, | |
708 | + not_<is_nothrow_move_constructible<_type>>> | |
709 | +{}; | |
710 | +//!@} | |
711 | + | |
712 | + | |
713 | +//! \pre 参数是完整的对象类型。 | |
714 | +//!@{ | |
715 | +//! \since build 983 | |
716 | +template<typename _type> | |
717 | +using bit_width_t = size_t_<sizeof(_type) * CHAR_BIT>; | |
718 | + | |
719 | +//! \since build 843 | |
720 | +template<typename _type> | |
721 | +using sizeof_t = size_t_<sizeof(_type)>; | |
722 | +//!@} | |
723 | +//!@} | |
724 | + | |
725 | + | |
726 | +//! \ingroup binary_type_traits | |
727 | +//!@{ | |
728 | +/*! | |
729 | +\pre 类型参数相同或满足同 ISO C++ 对 is_convertible 的要求。 | |
730 | +\since build 832 | |
731 | + | |
732 | +对类型参数的具体要求是两个类型参数都满足以下之一: | |
733 | + 完整类型。 | |
734 | + (可能 cv 修饰的) \c void 。 | |
735 | + 未知大小的数组。 | |
736 | +*/ | |
737 | +//!@{ | |
738 | +//! \brief 判断指定类型是否可被指定参数类型构造且要求显式构造。 | |
739 | +template <typename _type, typename _tFrom> | |
740 | +struct is_explicitly_constructible : and_<is_constructible<_type, _tFrom>, | |
741 | + not_<is_convertible<_tFrom, _type>>> | |
742 | +{}; | |
743 | + | |
744 | + | |
745 | +//! \brief 判断指定类型是否可被指定参数类型无异常抛出构造且要求显式构造。 | |
746 | +template <typename _type, typename _tFrom> | |
747 | +struct is_explicitly_nothrow_constructible : and_<is_nothrow_constructible< | |
748 | + _type, _tFrom>, not_<is_convertible<_tFrom, _type>>> | |
749 | +{}; | |
750 | + | |
751 | + | |
752 | +//! \brief 判断指定类型是否可被指定参数类型构造且可隐式构造。 | |
753 | +template <typename _type, typename _tFrom> | |
754 | +struct is_implicitly_constructible : and_<is_constructible<_type, _tFrom>, | |
755 | + is_convertible<_tFrom, _type>> | |
756 | +{}; | |
757 | + | |
758 | + | |
759 | +//! \brief 判断指定类型是否可被指定参数类型无异常抛出构造且可隐式构造。 | |
760 | +template <typename _type, typename _tFrom> | |
761 | +struct is_implicitly_nothrow_constructible : and_<is_nothrow_constructible< | |
762 | + _type, _tFrom>, is_convertible<_tFrom, _type>> | |
763 | +{}; | |
764 | +//!@} | |
765 | + | |
766 | + | |
767 | +/*! | |
768 | +\brief 判断指定类型之间添加 cv 限定符后是否相同。 | |
769 | +\since build 983 | |
770 | +*/ | |
771 | +template<typename _type1, typename _type2> | |
772 | +struct is_affinity : is_same<_t<std::add_cv<_type1>>, _t<std::add_cv<_type2>>> | |
773 | +{}; | |
774 | + | |
775 | + | |
776 | +/*! | |
777 | +\pre 类型参数相同或满足同 ISO C++ 对 is_convertible 的要求。 | |
778 | + | |
779 | +对类型参数的具体要求是满足以下之一: | |
780 | + 两个类型参数相同。 | |
781 | + 两个类型参数都满足以下之一: | |
782 | + 完整类型。 | |
783 | + (可能 cv 修饰的) \c void 。 | |
784 | + 未知大小的数组。 | |
785 | +*/ | |
786 | +//!@{ | |
787 | +/*! | |
788 | +\brief 判断指定类型之间是否相同或可转换。 | |
789 | +\note 类似 is_convertible ,但类型相同时不要求完整类型。 | |
790 | +\since build 850 | |
791 | +*/ | |
792 | +template<typename _type1, typename _type2> | |
793 | +struct is_same_or_convertible : details::is_same_or_convertible<_type1, _type2> | |
794 | +{}; | |
795 | + | |
796 | + | |
797 | +/*! | |
798 | +\brief 判断指定类型之间是否相同或可互相转换。 | |
799 | +\since build 575 | |
800 | +*/ | |
801 | +template<typename _type1, typename _type2> | |
802 | +struct is_interoperable : or_<is_same_or_convertible<_type1, _type2>, | |
803 | + is_same_or_convertible<_type2, _type1>> | |
804 | +{}; | |
805 | +//!@} | |
806 | + | |
807 | + | |
808 | +/*! | |
809 | +\brief 判断第一参数和第二参数指定的参数类型相同。 | |
810 | +\since build 865 | |
811 | +*/ | |
812 | +template<typename _type, typename _tParam> | |
813 | +struct is_same_param : is_same<_type&, _t<std::decay<_tParam>>&> | |
814 | +{}; | |
815 | +//!@} | |
816 | + | |
817 | + | |
818 | +//! \ingroup unary_type_traits | |
819 | +//!@{ | |
820 | +//! \since build 671 | |
821 | +//!@{ | |
822 | +//! \brief 判断第一参数和之后的参数指定的类型相同。 | |
823 | +template<typename _type, typename... _types> | |
824 | +struct are_same : and_<is_same<_type, _types>...> | |
825 | +{}; | |
826 | + | |
827 | + | |
828 | +//! \brief 判断第一参数在之后参数指定的类型中出现。 | |
829 | +template<typename _type, typename... _types> | |
830 | +struct is_in_types : or_<is_same<_type, _types>...> | |
831 | +{}; | |
832 | +//!@} | |
833 | + | |
834 | + | |
835 | +//!@{ | |
836 | +//! \brief 判断第一参数和之后的参数指定的类型添加 cv 限定符后相同。 | |
837 | +template<typename _type, typename... _types> | |
838 | +struct are_affinity : and_<is_affinity<_type, _types>...> | |
839 | +{}; | |
840 | + | |
841 | + | |
842 | +//! \brief 判断第一参数和之后的参数指定的类型添加 cv 限定符后相同。 | |
843 | +template<typename _type, typename... _types> | |
844 | +struct is_in_affinity_types : or_<is_affinity<_type, _types>...> | |
845 | +{}; | |
846 | +//!@} | |
239 | 847 | //!@} |
240 | 848 | |
241 | 849 | } // namespace ystdex; |
@@ -1,23 +1,22 @@ | ||
1 | 1 | /* |
2 | - © 2011-2019, 2021 FrankHB. | |
2 | + © 2011-2019, 2021, 2024 FrankHB. | |
3 | 3 | |
4 | - This file is part of the YSLib project, and may only be used, | |
5 | - modified, and distributed under the terms of the YSLib project | |
6 | - license, LICENSE.TXT. By continuing to use, modify, or distribute | |
7 | - this file you indicate that you have read the license and | |
8 | - understand and accept it fully. | |
4 | + This file is part of the YSLib project, and may only be used, modified, | |
5 | + and distributed under the terms of the YSLib project license. | |
6 | + By continuing to use, modify, or distribute this file you indicate that | |
7 | + you have read the license and understand and accept it fully. | |
9 | 8 | */ |
10 | 9 | |
11 | 10 | /*! \file type_traits.hpp |
12 | 11 | \ingroup YStandardEx |
13 | 12 | \brief ISO C++ 类型特征扩展。 |
14 | -\version r2038 | |
13 | +\version r2122 | |
15 | 14 | \author FrankHB <frankhb1989@gmail.com> |
16 | 15 | \since build 201 |
17 | 16 | \par 创建时间: |
18 | 17 | 2015-11-04 09:34:17 +0800 |
19 | 18 | \par 修改时间: |
20 | - 2021-11-11 20:32 +0800 | |
19 | + 2024-04-16 22:20 +0800 | |
21 | 20 | \par 文本编码: |
22 | 21 | UTF-8 |
23 | 22 | \par 模块名称: |
@@ -37,7 +36,7 @@ | ||
37 | 36 | { |
38 | 37 | |
39 | 38 | //! \ingroup transformation_traits |
40 | -//@{ | |
39 | +//!@{ | |
41 | 40 | /*! |
42 | 41 | \note 参数可能是不完整类型。 |
43 | 42 | \note 保证不依赖非推导上下文实现简单类型操作,可用于可推导的转换函数的名称。 |
@@ -45,7 +44,7 @@ | ||
45 | 44 | \sa CWG 395 |
46 | 45 | \since build 756 |
47 | 46 | */ |
48 | -//@{ | |
47 | +//!@{ | |
49 | 48 | template<typename _type> |
50 | 49 | using id_t = _type; |
51 | 50 |
@@ -57,76 +56,151 @@ | ||
57 | 56 | |
58 | 57 | template<typename _type> |
59 | 58 | using add_rref_t = _type&&; |
60 | -//@} | |
59 | +//!@} | |
61 | 60 | |
62 | 61 | |
62 | +//! \since build 983 | |
63 | +//!@{ | |
64 | +#define YB_Impl_TypeTraits_unary_op_t(_n, _op) \ | |
65 | + template<typename _type> \ | |
66 | + using _n = decltype(_op std::declval<_type>()); | |
67 | + | |
63 | 68 | //! \since build 669 |
64 | -//@{ | |
65 | -template<typename _type> | |
66 | -using addrof_t = decltype(&std::declval<_type>()); | |
69 | +//!@{ | |
70 | +YB_Impl_TypeTraits_unary_op_t(addrof_t, &) | |
67 | 71 | |
68 | -template<typename _type> | |
69 | -using indirect_t = decltype(*std::declval<_type>()); | |
70 | -//@} | |
72 | +YB_Impl_TypeTraits_unary_op_t(indirect_t, *) | |
73 | +//!@} | |
71 | 74 | |
72 | 75 | //! \since build 671 |
73 | 76 | template<typename _type> |
74 | 77 | using indirect_element_t = remove_reference_t<indirect_t<_type>>; |
75 | 78 | |
79 | +#define YB_Impl_TypeTraits_unary_post_op_t(_n, _op) \ | |
80 | + template<typename _type> \ | |
81 | + using _n = decltype(std::declval<_type>() _op); | |
82 | + | |
76 | 83 | //! \since build 865 |
77 | -template<typename _type> | |
78 | -using increment_t = decltype(++std::declval<_type>()); | |
84 | +YB_Impl_TypeTraits_unary_op_t(increment_t, ++) | |
79 | 85 | |
80 | 86 | //! \since build 867 |
81 | -//@{ | |
82 | -template<typename _type> | |
83 | -using increment_post_t = decltype(std::declval<_type>()--); | |
87 | +//!@{ | |
88 | +YB_Impl_TypeTraits_unary_post_op_t(increment_post_t, ++) | |
84 | 89 | |
85 | -template<typename _type> | |
86 | -using decrement_t = decltype(++std::declval<_type>()); | |
90 | +YB_Impl_TypeTraits_unary_op_t(decrement_t, --) | |
87 | 91 | |
88 | -template<typename _type> | |
89 | -using decrement_post_t = decltype(std::declval<_type>()--); | |
92 | +YB_Impl_TypeTraits_unary_post_op_t(decrement_post_t, --) | |
90 | 93 | |
91 | 94 | template<typename _type, typename _type2> |
92 | 95 | using subscript_t = decltype(std::declval<_type>()[std::declval<_type2>()]); |
96 | +//!@} | |
93 | 97 | |
98 | +#undef YB_Impl_TypeTraits_unary_post_op_t | |
99 | + | |
100 | +#define YB_Impl_TypeTraits_binary_op_t(_n, _op) \ | |
101 | + template<typename _type, typename _type2 = _type> \ | |
102 | + using _n = decltype(std::declval<_type>() _op std::declval<_type2>()); | |
103 | + | |
104 | +YB_Impl_TypeTraits_binary_op_t(plus_t, +) | |
105 | + | |
106 | +YB_Impl_TypeTraits_binary_op_t(minus_t, -) | |
107 | + | |
108 | +YB_Impl_TypeTraits_binary_op_t(multiplies_t, *) | |
109 | + | |
110 | +YB_Impl_TypeTraits_binary_op_t(divides_t, /) | |
111 | + | |
112 | +YB_Impl_TypeTraits_binary_op_t(modulus_t, %) | |
113 | + | |
114 | +YB_Impl_TypeTraits_unary_op_t(negate, -) | |
115 | + | |
116 | +//! \since build 867 | |
117 | +//!@{ | |
94 | 118 | #if YB_IMPL_GNUCPP || YB_IMPL_CLANGPP |
95 | 119 | YB_Diag_Push |
96 | 120 | YB_Diag_Ignore(float-equal) |
97 | 121 | #endif |
98 | -template<typename _type, typename _type2 = _type> | |
99 | -using equal_t = decltype(std::declval<_type>() == std::declval<_type2>()); | |
122 | +YB_Impl_TypeTraits_binary_op_t(equal_t, ==) | |
100 | 123 | |
101 | -template<typename _type, typename _type2 = _type> | |
102 | -using not_equal_t = decltype(std::declval<_type>() != std::declval<_type2>()); | |
124 | +YB_Impl_TypeTraits_binary_op_t(not_equal_t, !=) | |
103 | 125 | #if YB_IMPL_GNUCPP || YB_IMPL_CLANGPP |
104 | 126 | YB_Diag_Pop |
105 | 127 | #endif |
106 | -//@} | |
128 | +//!@} | |
129 | + | |
130 | +YB_Impl_TypeTraits_binary_op_t(greater_t, >) | |
131 | + | |
132 | +YB_Impl_TypeTraits_binary_op_t(less_t, <) | |
133 | + | |
134 | +YB_Impl_TypeTraits_binary_op_t(greater_equal_t, >=) | |
135 | + | |
136 | +YB_Impl_TypeTraits_binary_op_t(less_equal_t, <=) | |
137 | + | |
138 | +YB_Impl_TypeTraits_binary_op_t(right_shift_t, >>) | |
139 | + | |
140 | +YB_Impl_TypeTraits_binary_op_t(left_shift_t, <<) | |
141 | + | |
142 | +YB_Impl_TypeTraits_binary_op_t(logical_and_t, &&) | |
143 | + | |
144 | +YB_Impl_TypeTraits_binary_op_t(logical_or_t, ||) | |
145 | + | |
146 | +YB_Impl_TypeTraits_unary_op_t(logical_not_t, !) | |
147 | + | |
148 | +YB_Impl_TypeTraits_binary_op_t(bit_and_t, &) | |
149 | + | |
150 | +YB_Impl_TypeTraits_binary_op_t(bit_or_t, |) | |
151 | + | |
152 | +YB_Impl_TypeTraits_binary_op_t(bit_xor_t, ^) | |
153 | + | |
154 | +YB_Impl_TypeTraits_unary_op_t(bit_not_t, ~) | |
155 | + | |
156 | +YB_Impl_TypeTraits_binary_op_t(assignment_t, =) | |
157 | + | |
158 | +YB_Impl_TypeTraits_binary_op_t(plus_assignment_t, +=) | |
159 | + | |
160 | +YB_Impl_TypeTraits_binary_op_t(minus_assignment_t, -=) | |
161 | + | |
162 | +YB_Impl_TypeTraits_binary_op_t(multiplies_assignment_t, *=) | |
163 | + | |
164 | +YB_Impl_TypeTraits_binary_op_t(divides_assignment_t, /=) | |
165 | + | |
166 | +YB_Impl_TypeTraits_binary_op_t(modulus_assignment_t, %=) | |
167 | + | |
168 | +YB_Impl_TypeTraits_binary_op_t(right_shift_assignment_t, >>=) | |
169 | + | |
170 | +YB_Impl_TypeTraits_binary_op_t(left_shift_assignment_t, <<=) | |
171 | + | |
172 | +YB_Impl_TypeTraits_binary_op_t(bit_and_assignment_t, &=) | |
173 | + | |
174 | +YB_Impl_TypeTraits_binary_op_t(bit_or_assignment_t, |=) | |
175 | + | |
176 | +YB_Impl_TypeTraits_binary_op_t(bit_xor_assignment_t, ^=) | |
177 | + | |
178 | +#undef YB_Impl_TypeTraits_binary_op_t | |
179 | +#undef YB_Impl_TypeTraits_unary_op_t | |
180 | +//!@} | |
107 | 181 | |
108 | 182 | |
109 | 183 | //! \since build 830 |
110 | -//@{ | |
184 | +//!@{ | |
111 | 185 | template<typename _type> |
112 | 186 | using first_t = decltype(std::declval<_type>().first); |
113 | 187 | |
114 | 188 | template<typename _type> |
115 | 189 | using second_t = decltype(std::declval<_type>().second); |
116 | -//@} | |
117 | -//@} | |
118 | -//@} | |
190 | +//!@} | |
191 | +//!@} | |
192 | +//!@} | |
119 | 193 | |
120 | 194 | |
121 | 195 | //! \ingroup binary_type_traits |
122 | -//@{ | |
196 | +//!@{ | |
123 | 197 | /*! |
124 | 198 | \brief 判断是否存在合式的结果为非 void 类型的 [] 操作符接受指定类型的表达式。 |
125 | 199 | \since build 399 |
126 | 200 | */ |
127 | 201 | template<typename _type1, typename _type2> |
128 | 202 | struct has_subscription |
129 | - : bool_<is_detected<subscript_t, _type1, _type2>::value | |
203 | + : bool_<is_detected<subscript_t, _type1, _type2>() | |
130 | 204 | && !is_void<detected_t<subscript_t, _type1, _type2>>::value> |
131 | 205 | {}; |
132 | 206 |
@@ -139,7 +213,7 @@ | ||
139 | 213 | struct has_equality_operator |
140 | 214 | : is_detected_convertible<bool, equal_t, _type, _type2> |
141 | 215 | {}; |
142 | -//@} | |
216 | +//!@} | |
143 | 217 | |
144 | 218 | } // namespace ystdex; |
145 | 219 |
@@ -1,23 +1,22 @@ | ||
1 | 1 | /* |
2 | - © 2014, 2016, 2018 FrankHB. | |
2 | + © 2014, 2016, 2018, 2024 FrankHB. | |
3 | 3 | |
4 | - This file is part of the YSLib project, and may only be used, | |
5 | - modified, and distributed under the terms of the YSLib project | |
6 | - license, LICENSE.TXT. By continuing to use, modify, or distribute | |
7 | - this file you indicate that you have read the license and | |
8 | - understand and accept it fully. | |
4 | + This file is part of the YSLib project, and may only be used, modified, | |
5 | + and distributed under the terms of the YSLib project license. | |
6 | + By continuing to use, modify, or distribute this file you indicate that | |
7 | + you have read the license and understand and accept it fully. | |
9 | 8 | */ |
10 | 9 | |
11 | 10 | /*! \file exception.cpp |
12 | 11 | \ingroup YStandardEx |
13 | 12 | \brief 标准库异常扩展接口。 |
14 | -\version r59 | |
13 | +\version r75 | |
15 | 14 | \author FrankHB <frankhb1989@gmail.com> |
16 | 15 | \since build 556 |
17 | 16 | \par 创建时间: |
18 | 17 | 2014-11-28 12:15:16 +0800 |
19 | 18 | \par 修改时间: |
20 | - 2018-12-26 19:45 +0800 | |
19 | + 2024-04-12 23:34 +0800 | |
21 | 20 | \par 文本编码: |
22 | 21 | UTF-8 |
23 | 22 | \par 模块名称: |
@@ -64,5 +63,18 @@ | ||
64 | 63 | throw allocator_mismatch_error(); |
65 | 64 | } |
66 | 65 | |
66 | + | |
67 | +void | |
68 | +throw_overflow_error(const char* what_arg) | |
69 | +{ | |
70 | + throw std::overflow_error(what_arg); | |
71 | +} | |
72 | + | |
73 | +void | |
74 | +throw_underflow_error(const char* what_arg) | |
75 | +{ | |
76 | + throw std::underflow_error(what_arg); | |
77 | +} | |
78 | + | |
67 | 79 | } // namespace ystdex; |
68 | 80 |
@@ -1,23 +1,22 @@ | ||
1 | 1 | /* |
2 | - © 2010-2023 FrankHB. | |
2 | + © 2010-2024 FrankHB. | |
3 | 3 | |
4 | - This file is part of the YSLib project, and may only be used, | |
5 | - modified, and distributed under the terms of the YSLib project | |
6 | - license, LICENSE.TXT. By continuing to use, modify, or distribute | |
7 | - this file you indicate that you have read the license and | |
8 | - understand and accept it fully. | |
4 | + This file is part of the YSLib project, and may only be used, modified, | |
5 | + and distributed under the terms of the YSLib project license. | |
6 | + By continuing to use, modify, or distribute this file you indicate that | |
7 | + you have read the license and understand and accept it fully. | |
9 | 8 | */ |
10 | 9 | |
11 | 10 | /*! \file YCoreUtilities.h |
12 | 11 | \ingroup Core |
13 | 12 | \brief 核心实用模块。 |
14 | -\version r2719 | |
13 | +\version r2740 | |
15 | 14 | \author FrankHB <frankhb1989@gmail.com> |
16 | 15 | \since build 539 |
17 | 16 | \par 创建时间: |
18 | 17 | 2010-05-23 06:10:59 +0800 |
19 | 18 | \par 修改时间: |
20 | - 2023-03-26 02:57 +0800 | |
19 | + 2024-04-07 00:09 +0800 | |
21 | 20 | \par 文本编码: |
22 | 21 | UTF-8 |
23 | 22 | \par 模块名称: |
@@ -32,7 +31,9 @@ | ||
32 | 31 | #include YFM_YSLib_Core_YException // for LoggedEvent, string, string_view, |
33 | 32 | // std::string, std::exception, size_t, ExtractException, FatalError, |
34 | 33 | // to_std_string, make_string_view, linked_map; |
35 | -#include <ystdex/algorithm.hpp> // for ystdex::clamp; | |
34 | +#include <ystdex/algorithm.hpp> // for ystdex::clamp, ystdex::trivially_fill_n; | |
35 | +#include <ystdex/cstdint.hpp> // for ystdex::common_int_type_t, | |
36 | +// std::numeric_limits (with fixes); | |
36 | 37 | |
37 | 38 | namespace YSLib |
38 | 39 | { |
@@ -320,10 +321,9 @@ | ||
320 | 321 | inline _tDst |
321 | 322 | CheckLowerBound(_type val, const string& name = {}, RecordLevel lv = Err) |
322 | 323 | { |
323 | - using namespace ystdex; | |
324 | 324 | // XXX: See WG21 N3387. |
325 | 325 | // TODO: Add and use safe %common_arithmetic_type interface instead? |
326 | - using common_t = typename ystdex::common_int_type<_tDst, _type>::type; | |
326 | + using common_t = ystdex::common_int_type_t<_tDst, _type>; | |
327 | 327 | |
328 | 328 | if(!(common_t(val) < common_t(std::numeric_limits<_tDst>::min()))) |
329 | 329 | return _tDst(val); |
@@ -336,11 +336,10 @@ | ||
336 | 336 | inline _tDst |
337 | 337 | CheckUpperBound(_type val, const string& name = {}, RecordLevel lv = Err) |
338 | 338 | { |
339 | - using namespace ystdex; | |
340 | 339 | // XXX: See WG21 N3387. |
341 | 340 | // TODO: Add and use safe %common_arithmetic_type interface instead? |
342 | 341 | // TODO: Add direct integer rank comparison? |
343 | - using common_t = typename ystdex::common_int_type<_tDst, _type>::type; | |
342 | + using common_t = ystdex::common_int_type_t<_tDst, _type>; | |
344 | 343 | |
345 | 344 | if((std::is_signed<common_t>() && std::is_unsigned<_tDst>() |
346 | 345 | && ystdex::integer_width<common_t>() <= ystdex::integer_width<_tDst>()) |
@@ -385,21 +384,14 @@ | ||
385 | 384 | |
386 | 385 | /*! |
387 | 386 | \brief 清除指定的连续对象。 |
388 | -\pre 设类型 \c T 为 ystdex::decay_t<decltype(*dst)>,则应满足 | |
389 | - <tt>std::is_trivial\<T>() || (std::is_nothrow_default_constructible\<T>() | |
390 | - && std::is_nothrow_assignable\<T, T>())</tt> 。 | |
387 | +\pre 满足 \c ystdex::trivially_fill_n 相同的要求。 | |
391 | 388 | \since build 624 |
392 | 389 | */ |
393 | 390 | template<typename _tOut> |
394 | 391 | inline void |
395 | 392 | ClearSequence(_tOut dst, size_t n) ynothrowv |
396 | 393 | { |
397 | - using _type = ystdex::decay_t<decltype(*dst)>; | |
398 | - static_assert(std::is_trivial<_type>() | |
399 | - || (std::is_nothrow_default_constructible<_type>() | |
400 | - && std::is_nothrow_assignable<_type, _type>()), "Invalid type found."); | |
401 | - | |
402 | - std::fill_n(dst, n, _type()); | |
394 | + ystdex::trivially_fill_n(dst, n); | |
403 | 395 | } |
404 | 396 | |
405 | 397 |
@@ -1,5 +1,5 @@ | ||
1 | 1 | /* |
2 | - © 2011-2016, 2018-2021, 2023 FrankHB. | |
2 | + © 2011-2016, 2018-2021, 2023-2024 FrankHB. | |
3 | 3 | |
4 | 4 | This file is part of the YSLib project, and may only be used, modified, |
5 | 5 | and distributed under the terms of the YSLib project license. |
@@ -10,13 +10,13 @@ | ||
10 | 10 | /*! \file YGDIBase.h |
11 | 11 | \ingroup Core |
12 | 12 | \brief 平台无关的基础图形学对象。 |
13 | -\version r2645 | |
13 | +\version r2647 | |
14 | 14 | \author FrankHB <frankhb1989@gmail.com> |
15 | 15 | \since build 563 |
16 | 16 | \par 创建时间: |
17 | 17 | 2011-05-03 07:20:51 +0800 |
18 | 18 | \par 修改时间: |
19 | - 2023-11-09 15:36 +0800 | |
19 | + 2024-04-06 16:27 +0800 | |
20 | 20 | \par 文本编码: |
21 | 21 | UTF-8 |
22 | 22 | \par 模块名称: |
@@ -30,7 +30,7 @@ | ||
30 | 30 | #include "YModules.h" |
31 | 31 | #include YFM_YSLib_Core_YCoreUtilities // for octet, size_t, Pixel, |
32 | 32 | // ystdex::min, ystdex::max, YSLib::HalfDifference; |
33 | -#include <limits> // for std::numeric_limits; | |
33 | +#include <libdefect/limits.hpp> // for std::numeric_limits (with fixes); | |
34 | 34 | #include <ystdex/operators.hpp> // for ystdex::equality_comparable; |
35 | 35 | #include <ystdex/string.hpp> // for ystdex::quote; |
36 | 36 |
@@ -1,5 +1,5 @@ | ||
1 | 1 | /* |
2 | - © 2009-2017, 2019, 2021-2023 FrankHB. | |
2 | + © 2009-2017, 2019, 2021-2024 FrankHB. | |
3 | 3 | |
4 | 4 | This file is part of the YSLib project, and may only be used, modified, |
5 | 5 | and distributed under the terms of the YSLib project license. |
@@ -10,13 +10,13 @@ | ||
10 | 10 | /*! \file YGDI.h |
11 | 11 | \ingroup Service |
12 | 12 | \brief 平台无关的图形设备接口。 |
13 | -\version r4084 | |
13 | +\version r4089 | |
14 | 14 | \author FrankHB <frankhb1989@gmail.com> |
15 | 15 | \since build 566 |
16 | 16 | \par 创建时间: |
17 | 17 | 2009-12-14 18:29:46 +0800 |
18 | 18 | \par 修改时间: |
19 | - 2023-12-20 20:26 +0800 | |
19 | + 2024-03-30 23:45 +0800 | |
20 | 20 | \par 文本编码: |
21 | 21 | UTF-8 |
22 | 22 | \par 模块名称: |
@@ -224,7 +224,7 @@ | ||
224 | 224 | |
225 | 225 | /*! |
226 | 226 | \brief 标准矩形像素图缓冲区。 |
227 | -\post 满足 \c ystdex::is_nothrow_moveable<CompactPixmap>()</tt> 。 | |
227 | +\post 满足 \c ystdex::is_nothrow_movable<CompactPixmap>()</tt> 。 | |
228 | 228 | \note 保证像素数据连续。 |
229 | 229 | \since build 418 |
230 | 230 | */ |
@@ -325,13 +325,13 @@ | ||
325 | 325 | \relates CompactPixmap |
326 | 326 | \since build 630 |
327 | 327 | */ |
328 | -static_assert(ystdex::is_nothrow_moveable<CompactPixmap>(), | |
328 | +static_assert(ystdex::is_nothrow_movable<CompactPixmap>(), | |
329 | 329 | "Postcondition failed."); |
330 | 330 | |
331 | 331 | |
332 | 332 | /*! |
333 | 333 | \brief 使用 8 位 Alpha 扩展的标准矩形像素图缓冲区。 |
334 | -\post 满足 \c ystdex::is_nothrow_moveable<CompactPixmapEx>()</tt> 。 | |
334 | +\post 满足 \c ystdex::is_nothrow_movable<CompactPixmapEx>()</tt> 。 | |
335 | 335 | \note 保证像素数据和 Alpha 数据分别连续。 |
336 | 336 | */ |
337 | 337 | class YF_API CompactPixmapEx : public CompactPixmap |
@@ -405,7 +405,7 @@ | ||
405 | 405 | \relates CompactPixmapEx |
406 | 406 | \since build 630 |
407 | 407 | */ |
408 | -static_assert(ystdex::is_nothrow_moveable<CompactPixmapEx>(), | |
408 | +static_assert(ystdex::is_nothrow_movable<CompactPixmapEx>(), | |
409 | 409 | "Postcondition failed."); |
410 | 410 | |
411 | 411 |
@@ -10,13 +10,13 @@ | ||
10 | 10 | /*! \file ChangeLog.V0.9.txt |
11 | 11 | \ingroup Documentation |
12 | 12 | \brief 版本更新历史记录 - V0.9 。 |
13 | -\version r20590 | |
13 | +\version r20988 | |
14 | 14 | \author FrankHB <frankhb1989@gmail.com> |
15 | 15 | \since build 900 |
16 | 16 | \par 创建时间: |
17 | 17 | 2020-10-12 17:19:23 +0800 |
18 | 18 | \par 修改时间: |
19 | - 2024-02-27 00:28 +0800 | |
19 | + 2024-04-19 22:27 +0800 | |
20 | 20 | \par 文本编码: |
21 | 21 | UTF-8 |
22 | 22 | \par 模块名称: |
@@ -31,6 +31,405 @@ | ||
31 | 31 | |
32 | 32 | $now |
33 | 33 | ( |
34 | + / "name with 'moveable'" => 'movable' @ "unary type traits %(is_moveable, \ | |
35 | + is_nothrow_moveable)" $effective @ %(YBase.YStandardEx.(Meta, Optional), | |
36 | + YFramework.YSLib.Service.YGDI) $dep_to "renamed moveable", | |
37 | + // See $2024-03 @ %Documentation::Workflow. | |
38 | + / %YBase $= | |
39 | + ( | |
40 | + / %YDefinition $= | |
41 | + ( | |
42 | + + $re_add(b962) "macro %_SILENCE_CXX23_DENORM_DEPRECATION_WARNING \ | |
43 | + if not defined" @ 'YB_IMPL_MSCPP >= 1937', | |
44 | + / $re_add(b977) "all accessible URLs" ^ 'https://' ~ 'http://', | |
45 | + + $re_add(b831) | |
46 | + "conditionally-defined macro %__has_constexpr_builtin", | |
47 | + ( | |
48 | + + "macro %YB_HAS_int128"; | |
49 | + + "macro %YB_Use_int128 if not defined"; | |
50 | + + "macro %YB_MaxIntBits", | |
51 | + + "aliases %(int128_t, uint128_t)" @ 'YB_Use_int128 > 0' | |
52 | + ) | |
53 | + ), | |
54 | + + %Limits @ %LibDefects, | |
55 | + / %YStandardEx $= | |
56 | + ( | |
57 | + / %TypeInspection $= | |
58 | + ( | |
59 | + / ^ $dep_from ("%_t" @ %Meta) $= | |
60 | + ( | |
61 | + / DLDI "simplified %is_null_pointer" | |
62 | + @ '__cpp_lib_is_null_pointer >= 201309L', | |
63 | + + "unary type trait %is_extended_integer" | |
64 | + ^ $dep_from ("%(int128_t, uint128_t)" @ %YDefinition) | |
65 | + ), | |
66 | + * $re_add(b969) DD "unbalanced Doxygen group markers" | |
67 | + $since b669, | |
68 | + + "unary type trait %bit_width_t", | |
69 | + // No %bit_width, and %std::bit_width is not for types. | |
70 | + ( | |
71 | + + "binary type trait %is_affinity"; | |
72 | + + "unary type traits %(are_affinity, is_in_affinity_types)" | |
73 | + ), | |
74 | + + "support of optional 128-bit integers" $effective | |
75 | + @ "unary type traits %(is_integral, is_arithmetic, \ | |
76 | + is_fundamental, is_scalar, is_coumpound, is_signed, \ | |
77 | + is_unsigned)" ^ $dep_from ("%YB_Use_int128" @ %YDefinition), | |
78 | + * "wrong result for possibly cv-qualified %nullptr_t" | |
79 | + @ '!YB_HAS_BUILTIN_NULLPTR' $effective @ "unary type \ | |
80 | + traits %(is_class, is_arithmetic, is_fundamental, \ | |
81 | + is_scalar, is_compound)" $orig | |
82 | + (@ '!YCL_HAS_BUILTIN_NULLPTR' @ %TypeOperations $since b245) | |
83 | + // There was %YCL_HAS_BUILTIN_NULLPTR since b245 which was \ | |
84 | + renamed to %YB_HAS_BUILTIN_NULLPTR in b313. | |
85 | + ), | |
86 | + / %Meta $= | |
87 | + ( | |
88 | + + DD '\ingroup YBase_replacement_features' @ "Doxygen comment" | |
89 | + @ "struct %nonesuch", | |
90 | + * $re_add(b937) $lib $impl "missing undefining \ | |
91 | + 'YB_Impl_TypeTraits_has_cpp20_common_type'" $since b938, | |
92 | + ( | |
93 | + / "metafunction %_t" >> %TypeInspection; | |
94 | + / DLDI "simplified all alias templates with '_t' as the suffix \ | |
95 | + of name for accessing member 'type' of type trait class \ | |
96 | + templates" ^ "%_t" ~ 'typename' | |
97 | + ), | |
98 | + * "inconsistent type traits %(is_trivially_copyable, \ | |
99 | + is_trivially_moveable)" $orig (@ %TypeOperation $since b630) | |
100 | + $= | |
101 | + ( | |
102 | + // See $2024-03 @ %Documentation::Workflow. | |
103 | + / $re_add(b727) $revert_ex(b650) "%unary_type_trait \ | |
104 | + is_trivially_copyable" | |
105 | + -> ('using std::is_trivially_copyable' | |
106 | + @ "inline namespace %cpp2011" @ %TypeInspection), | |
107 | + - $revert(b630) "unary type trait %is_trivially_moveable" | |
108 | + ), | |
109 | + ( | |
110 | + / DD @ "Doxygen comment" @ "unary type traits \ | |
111 | + %(is_unqualified_object, is_array_of_unqualified_object)" $= | |
112 | + ( | |
113 | + * "wrong group name" $since b867 | |
114 | + $= (/ 'unary_type_trait' -> 'unary_type_traits'), | |
115 | + * "wrong description" @ "'\brief' command" | |
116 | + @ ("%is_unqualified_object" $since b867, | |
117 | + "%is_array_of_unqualified_object" $since b972) | |
118 | + ), | |
119 | + * DD "missing type requirement" @ "Doxygen comment" | |
120 | + @ ("unary type trait %is_returnable" | |
121 | + $orig (@ %TypeOperation $since b333), | |
122 | + "unary type trait %sizeof_t" $since b843) $= | |
123 | + (+ $impl "'\pre' command and detailed description"), | |
124 | + / "unary type trait %is_array_of_unqualified_object" | |
125 | + >> %TypeInspection | |
126 | + ^ DLDI "%(_t, std::remove_extent)" ~ "%remove_extent_t", | |
127 | + * "missing the check of %is_trivially_destructible" | |
128 | + @ "unary type trait %is_trivially_movable" $sice | |
129 | + $dep_from "renamed moveable"; | |
130 | + / $lib "all unary type traits" >> %TypeInspection | |
131 | + ), | |
132 | + ( | |
133 | + / $lib "unary type trait %is_nonconst_object" >> %TypeInspection | |
134 | + $= (/ $dev $detail $impl "%(_t, std::add_const)" | |
135 | + $dep_from "%_t" ~ "%add_const_t"), | |
136 | + * DD "incorrect description" @ "'\brief' command" | |
137 | + @ "Doxygen comment" @ "unary type trait %is_object_pointer" | |
138 | + $since b522; | |
139 | + // This was wrongly same to that in %is_pointer_to_object, | |
140 | + / $lib "unary type trait %(is_pointer_to_object, \ | |
141 | + is_object_pointer, is_function_pointer, is_class_pointer, \ | |
142 | + is_lvalue_class_reference, is_rvalue_class_reference)" | |
143 | + >> %TypeInspection | |
144 | + $= (/ $dev $detail $impl "%(_t, std::remove_pointer)" | |
145 | + $dep_from "%_t" ~ "%remove_pointer_t") | |
146 | + ), | |
147 | + ( | |
148 | + / $lib ("unary type trait %is_decayed", | |
149 | + "binary type trait %is_same_param") >> %TypeInspection | |
150 | + $= (/ $dev $detail $impl ^ "%(_t, std::decay)" | |
151 | + $dep_from "%_t" ~ "%decay_t"), | |
152 | + / $lib "unary type trait %is_unqualified" >> %TypeInspection | |
153 | + $= (/ $dev $detail $impl ^ "%(_t, std::remove_cv)" | |
154 | + $dep_from "%_t" ~ "%remove_cv_t"); | |
155 | + / $lib ("unary type traits %(is_decayed, is_unqualified)", | |
156 | + "binary type trait %is_same_param") | |
157 | + @ "Doxygen group %type_traits_operations" | |
158 | + >> ("Doxygen group %unary_type_traits" @ %TypeInspection) | |
159 | + ), | |
160 | + / $lib ("unary type traits %(are_same, is_in_types)") | |
161 | + @ "Doxygen group %metafunctions" | |
162 | + >> ("Doxygen group %unary_type_traits" @ %TypeInspection) | |
163 | + ( | |
164 | + * $re_add(b722) "wrongly relied on the complete template \ | |
165 | + argument types" @ "binary type trait %is_interoperable" | |
166 | + $since b722 | |
167 | + // The change on the implementation was incomplete. | |
168 | + $= (/ $impl ^ "%is_same_or_convertible" | |
169 | + ~ "%is_convertible"), | |
170 | + * DD "missing type requirement" @ "Doxygen comment" | |
171 | + ("binary type trait %is_interoperable" $since b575, | |
172 | + "binary type traits %(is_explicitly_constructible, \ | |
173 | + is_explicitly_nothrow_constructible, \ | |
174 | + is_implicitly_constructible, \ | |
175 | + is_implicitly_nothrow_constructible)" $since b832) | |
176 | + (+ $impl "'\pre' command and detailed description"); | |
177 | + / "binary type traits %(is_same_or_convertible, \ | |
178 | + is_interoperable, is_explicitly_constructible, \ | |
179 | + is_explicitly_nothrow_constructible, \ | |
180 | + is_implicitly_constructible, \ | |
181 | + is_implicitly_nothrow_constructible)" >> %TypeInspection | |
182 | + ), | |
183 | + + "transformation traits %((copy_cv; copy_cv_t), \ | |
184 | + (copy_reference; copy_reference_t); copy_cvref; \ | |
185 | + copy_cvref_t)", | |
186 | + / DLI "optimized transforamtion type trait %remove_cvref" | |
187 | + @ '__has_builtin(__remove_cvref)', | |
188 | + + "support of optional 128-bit integers" $effective | |
189 | + @ "transformation type traits %(make_signed, make_unsigned)" | |
190 | + ^ $dep_from ("%YB_Use_int128" @ %YDefinition), | |
191 | + + "transformation trait %enable_if_floating_point_t" | |
192 | + ), | |
193 | + + %Limits $= | |
194 | + ( | |
195 | + + "traits %numeric_traits"; | |
196 | + + "unary type traits %(is_bounded_integer, \ | |
197 | + is_bounded_binary_integer, is_unbounded_number, \ | |
198 | + (is_arbitrary_unbounded_number; is_in_subrange_of), \ | |
199 | + has_special_value)", | |
200 | + + ("type trait %rep_in_digits10"; | |
201 | + "metafunction %enable_if_rep_in_digits10_t") | |
202 | + ), | |
203 | + / %CStandardInteger $= | |
204 | + ( | |
205 | + + "aliases %(intmax_t, uintmax_t)" ^ $dep_from | |
206 | + ((%YB_Use_int128, int128_t, uint128_t) @ %YDefinition), | |
207 | + ( | |
208 | + + "yconstfn function %promote_std_integer_width"; | |
209 | + + "yconstfn function %promote_integer_width" | |
210 | + ^ $dep_from ("%YB_Use_int128" @ %YDefinition), | |
211 | + / $comp "opted-in support of 128-bit integers" | |
212 | + @ "transformation trait %make_signed_c" | |
213 | + $dep_from ("%(make_signed, make_unsigned)" @ %Meta), | |
214 | + / $lib $impl @ "class template %make_width_int" $= | |
215 | + ( | |
216 | + ( | |
217 | + / $dev "loosed the static assertion" | |
218 | + ^ $dep_from ("%YB_MaxIntBits" @ %YDefinition) ~ '64'; | |
219 | + / $dev "simplified primary class template" | |
220 | + ^ "%promote_integer_width" | |
221 | + ), | |
222 | + + "optional specialization for 128-bit integers" | |
223 | + @ 'YB_Use_int128 > 0' $dep_to "128-bit widen integer" | |
224 | + $= (/ (^ $dep_from "%(int128_t, uint128_t") | |
225 | + @ %YDefinition, $dep_from "%make_signed_c")) | |
226 | + ) | |
227 | + ), | |
228 | + / "opted-in support of 128-bit integers" | |
229 | + ^ ("%YB_MaxIntBits" @ %YDefinition) ~ '64' | |
230 | + $dep_from "128-bit widen integer", | |
231 | + ( | |
232 | + + "alias template %make_widen_int_t"; | |
233 | + + "specialization of class template %make_widen_int for \ | |
234 | + cv-qualified types", | |
235 | + / DLDI "simplified specialization of %common_int_type" | |
236 | + ^ "%make_widen_int_t" ~ "%(_t, make_widen_int)" | |
237 | + ), | |
238 | + / @ "unary type trait %integer_width" $= | |
239 | + ( | |
240 | + / DLDI "simplified" ^ $dep_from ("%bit_width_t" | |
241 | + @ "%TypeInspection") ~ "%size_t_", | |
242 | + * "missing support types with different value \ | |
243 | + representation than the object representation" | |
244 | + $orig (@ %TypeOperation $since b260) | |
245 | + $= (/ $impl ^ ("%is_bounded_binary_integer" | |
246 | + @ %Limits, "%std::numeric_limits")) | |
247 | + ), | |
248 | + ( | |
249 | + * "invalid cast to %uintmax_t" | |
250 | + @ "binary type trait %have_same_modulo" $since b440; | |
251 | + // This was not working on non-integer types and 128-bit \ | |
252 | + types which are larger than %uintmax_t. | |
253 | + * "missing support of types other than unsigned integers" | |
254 | + @ "unary type trait %modular_arithmetic" $since b440 | |
255 | + $= (/ $impl ^ "%std::numeric_limits" ~ "%is_signed") | |
256 | + ), | |
257 | + + "transformation trait %common_int_t" | |
258 | + ), | |
259 | + + "functions %(throw_overflow_error, throw_underflow_error)" | |
260 | + @ %Exception, | |
261 | + + "%Arithmetic" $= | |
262 | + ( | |
263 | + + "function template %upow", | |
264 | + + "transformation traits %((extend_additive_overflow; \ | |
265 | + extend_additive_overflow_t, extend_additive_underflow; \ | |
266 | + extend_additive_underflow_t), (extend_product; \ | |
267 | + extend_product_t))" | |
268 | + ^ ("%remove_cv", $dep_from ("%copy_cv_t" @ %Meta)), | |
269 | + + "function templates %(checked_plus, checked_minus, \ | |
270 | + checked_multiply, extended_plus, extended_minus, \ | |
271 | + extended_multiply)" ^ $dep_from ("%is_unbounded_number" | |
272 | + @ Limits, "functions %(throw_overflow_error, \ | |
273 | + throw_underflow_error)" @ %Exception), | |
274 | + + "function template %checked_constant_multiply" | |
275 | + ), | |
276 | + + "unary type trait %is_timespec_like" @ %CTime, | |
277 | + + %Chrono $= | |
278 | + ( | |
279 | + + "namespace %ystdex::chrono" ^ $dep_from ("function \ | |
280 | + template %checked_constant_multiply" @ %Arithmetic, | |
281 | + "alias %intmax_t" @ %CStandardInteger) $= | |
282 | + ( | |
283 | + + "inline namespace cpp2011"; | |
284 | + + "inline namespace cpp2020", | |
285 | + + "function templates %(ns_to_timespec, timespec_to_ns)" | |
286 | + ^ $dep_from ("%is_timespec_like" @ %CTime), | |
287 | + + "type traits %(is_duration; enable_if_duration_t), \ | |
288 | + (is_time_point; enable_if_time_point_t)", | |
289 | + + "type traits unchecked_rep" | |
290 | + ^ $dep_from ("%is_unbounded_number" @ %Limits), | |
291 | + ( | |
292 | + + "functors %(checked_rep_caster, checked_max_rep_caster, \ | |
293 | + checked_min_rep_caster)" | |
294 | + ^ $dep_from ("functions %(throw_overflow_error, \ | |
295 | + throw_underflow_error)" @ %Exception); | |
296 | + + "function templates %(checked_rep_cast, \ | |
297 | + checked_max_rep_cast, checked_min_rep_cast)"; | |
298 | + + "function templates %(multiply_time, multiply_time_on)" | |
299 | + ^ $dep_from ("%ystdex::checked_constant_multiply" | |
300 | + @ %CStandardInteger); | |
301 | + + "function template %checked_duration_cast" | |
302 | + ^ $dep_from "%enable_if_duration_t"; | |
303 | + + "function template %checked_time_point_cast" | |
304 | + ^ $dep_from "%is_duration", | |
305 | + ), | |
306 | + + "function templates %(checked_plus, checked_minus)" | |
307 | + ^ $dep_from | |
308 | + ("%ystdex::(checked_plus, checked_minus)" @ %Arithmetic) | |
309 | + ) | |
310 | + ), | |
311 | + / DLDI "simplified functions %(floor_lb, ceiling_lb)" @ %Bit | |
312 | + ^ $dep_from ("%bit_width_t" @ %TypeInspection) ~ "%size_t_", | |
313 | + * $re_ex(b967) "exception specification" @ "function %swap" | |
314 | + @ "class template %mapped_set" @ %Set $since b830, | |
315 | + - $re_add(b982) DLDI "redundant parentheses around 'defined' \ | |
316 | + operator" @ "preprocessing directives" @ %(Allocator, Set), | |
317 | + / %Allocator $= | |
318 | + ( | |
319 | + / DD $re_add(b982) "merged multiple '\ingroup' commands" | |
320 | + @ "Doxygen comment", | |
321 | + + "workaround" | |
322 | + @ '__cplusplus >= 202002L && _LIBCPP_VERSION <= 160000' | |
323 | + ), | |
324 | + / %TypeTraits $= | |
325 | + ( | |
326 | + / $re_add(b982) DLDI "all '::value' not forming an operand to \ | |
327 | + an operator and not after a qualified type-id in class \ | |
328 | + scope" @ "other value contexts" -> '()' $effective | |
329 | + @ "binary type trait %has_subscription", | |
330 | + + "transformation traits %(plus_t, minus_t, multiplies_t, \ | |
331 | + divides_t, modulus_t, negate_t, greater_t, less_t, \ | |
332 | + greater_equal_t, less_equal_t, right_shift_t, \ | |
333 | + left_shift_t, logical_and_t, logical_or_t, logical_not_t, \ | |
334 | + bit_and_t, bit_or_t, bit_xor_t, bit_not_t, assignment_t, \ | |
335 | + plus_assignment_t, minus_assignment_t, \ | |
336 | + multiplies_assignment_t, divides_assignment_t, \ | |
337 | + modulus_assignment_t, right_shift_assignment_t, \ | |
338 | + left_shift_assignment_t, bit_and_assignment_t, \ | |
339 | + bit_or_assignment_t, bit_xor_assignment_t)", | |
340 | + / DLDI "simplified transformation traits" ^ "macros" | |
341 | + ), | |
342 | + / %Iterator $= | |
343 | + ( | |
344 | + / @ "class template %transformed_iterator" $= | |
345 | + ( | |
346 | + * "missing SFINAE-friendly condition for overloaded \ | |
347 | + operators" $effecitve @ ($re_ex(b685) ("all 2 friend \ | |
348 | + function templates %operator<" $since b600 ^ $dep_from | |
349 | + ("%less_t" @ %TypeTraits), "function %operator--" | |
350 | + $since b665 ^ ("%decrement_t" @ %TypeTraits), "all 3 \ | |
351 | + friend function templates %operator-" $since b667 | |
352 | + ^ $dep_from ("%minus_t" @ %TypeTraits), "functions \ | |
353 | + %operator(+=, -=)" $orig (@ "friend function" | |
354 | + since b600) ^ $dep_from ("%(plus_assignment_t, \ | |
355 | + minus_assignment_t)" @ %TypeTraits)), | |
356 | + // See $2024-03 @ %Documentation::Workflow. | |
357 | + * DD "wrong command" @ "Dogygen comments" @ "functions \ | |
358 | + %operator(*, ++, --)" | |
359 | + $since b576 (/ $impl '\brief' -> '\note') | |
360 | + ), | |
361 | + / @ "class template %tuple_iterator" $= | |
362 | + ( | |
363 | + * "missing SFINAE-friendly condition for overloaded \ | |
364 | + operators" $effecitve @ ($re_ex(b685) ("all 2 friend \ | |
365 | + function templates %operator<" $since b600 ^ $dep_from | |
366 | + ("%less_t" @ %TypeTraits), "function %operator--" | |
367 | + $since b665 ^ ("%decrement_t" @ %TypeTraits), "all 3 \ | |
368 | + friend function templates %operator-" $since b667 | |
369 | + ^ $dep_from ("%minus_t" @ %TypeTraits), "functions \ | |
370 | + %operator(+=, -=)" $orig (@ "friend function" | |
371 | + since b600) ^ $dep_from ("%(plus_assignment_t, \ | |
372 | + minus_assignment_t)" @ %TypeTraits)), | |
373 | + ) | |
374 | + ), | |
375 | + + "member type %has_member_overwrite_and_resize" | |
376 | + @ "trait %string_traits" @ %String, | |
377 | + ( | |
378 | + + %CharacterConversion; | |
379 | + ( | |
380 | + + "header inclusion %CharacterConversion" @ %String; | |
381 | + / ("header inclusion <numeric>", "function templates %(pack_uint, \ | |
382 | + unpack_uint, read_uint_be, read_uint_le, write_uint_be, \ | |
383 | + write_uint_le)") >> %CharacterConversion; | |
384 | + / DLI "lambda-expression" @ "function template %pack_uint" | |
385 | + @ %CharacterConversion ^ "%(YB_LAMBDA_ANNOTATE, ynothrow, pure)" | |
386 | + ), | |
387 | + / @ %CharacterConversion $= | |
388 | + ( | |
389 | + + "transformation trait %decimal_min_uint_t", | |
390 | + + "trait %double_digits_write_traits"; | |
391 | + + "trait %decimal_write_traits"; | |
392 | + + "class template %decimal_write" | |
393 | + ^ $dep_from ("%enable_if_rep_in_digits10_t" @ %Limits); | |
394 | + + "function tempate %write_decimal" | |
395 | + ^ $dep_from ("%upow" @ %Arithmetic); | |
396 | + + "function template %write_decimal_integer" | |
397 | + ^ ("%upow" @ %Arithmetic) | |
398 | + ); | |
399 | + / "%to_string" @ %String $= | |
400 | + ( | |
401 | + / $impl ^ $dep_from ("%write_decimal_integer" | |
402 | + @ "%CharacterConversion", | |
403 | + "%string_traits::has_member_overwrite_and_resize"); | |
404 | + + $comp "support of 128-bit integers if available" | |
405 | + ^ $dep_from ("%is_integral" @ %TypeInspection) | |
406 | + ) | |
407 | + ) | |
408 | + ) | |
409 | + ), | |
410 | + / $impl ^ "libstdc++ fixes of %std::numeric_limits fixes" | |
411 | + ^ $dep_from %YBase.LibDefect.Limits $= | |
412 | + // See $2024-04 @ %Documentation::Workflow. | |
413 | + ( | |
414 | + + "header inclusion %YBase.YStandardEx.CStandardInteger" $effective | |
415 | + @ %YFramework.YSLib.Core.YCoreUtilities; | |
416 | + / "header inclusion <limits>" -> "%YBase.LibDefect.Limits" $effective | |
417 | + @ %(YBase.YStandardEx.(Bit, CStandardInteger, CTime, Cast, List), | |
418 | + YFramework.YSLib.Core.YGDIBase) | |
419 | + ), | |
420 | + / $lib $impl %YFramework.YSLib.Core.YCoreUtilities $= | |
421 | + ( | |
422 | + / "simplified function template %ClearSequence" | |
423 | + ^ "%ystdex::trivially_fill_n", | |
424 | + / $dev $detail "function templates %(CheckLowerBound, \ | |
425 | + CheckUpperBound)" ^ ("%ystdex::common_int_type_t" | |
426 | + @ %YBase.YStandardEx.CStandardInteger) | |
427 | + ~ "%ysdex::common_int_type" | |
428 | + ) | |
429 | +), | |
430 | + | |
431 | +b982 | |
432 | +( | |
34 | 433 | / %YBase $= |
35 | 434 | ( |
36 | 435 | / %YStandardEx $= |
@@ -1,5 +1,5 @@ | ||
1 | 1 | /* |
2 | - © 2013-2023 FrankHB. | |
2 | + © 2013-2024 FrankHB. | |
3 | 3 | |
4 | 4 | This file is part of the YSLib project, and may only be used, modified, |
5 | 5 | and distributed under the terms of the YSLib project license. |
@@ -10,13 +10,13 @@ | ||
10 | 10 | /*! \file Workflow.txt |
11 | 11 | \ingroup Documentation |
12 | 12 | \brief 工作流汇总报告。 |
13 | -\version r5998 | |
13 | +\version r6202 | |
14 | 14 | \author FrankHB <frankhb1989@gmail.com> |
15 | 15 | \since build 433 |
16 | 16 | \par 创建时间: |
17 | 17 | 2013-07-31 01:27:41 +0800 |
18 | 18 | \par 修改时间: |
19 | - 2023-09-20 10:44 +0800 | |
19 | + 2024-04-16 02:15 +0800 | |
20 | 20 | \par 文本编码: |
21 | 21 | UTF-8 |
22 | 22 | \par 模块名称: |
@@ -5658,5 +5658,212 @@ | ||
5658 | 5658 | However, whether the implementation is required by newer standard not, this is at least not guaranteed to work by ISO C++11. |
5659 | 5659 | As a result, the status of YSLib issue 40 is not changed. |
5660 | 5660 | |
5661 | +2024-03: | |
5662 | + | |
5663 | +report.impl: | |
5664 | +YBase API is improved. | |
5665 | + Type traits in YBase are refactored, reworked and enhanced. | |
5666 | + Many traits are now moved to YBase module YStandardEx.TypeInspection from module YStandardEx.Meta, and a few new ones are added. | |
5667 | + These unary type traits are moved: 'is_array_of_unknown_bound', 'is_object_or_void', 'is_referenceable', 'is_returnable', 'is_class_type', 'is_trivial_class', 'is_trivial_class_type', 'is_trivial_union', 'is_inheritable_class', 'is_cv', 'is_decomposable', 'is_copyable, is_movable', 'is_nothrow_copyable', 'is_nothrow_movable', 'is_trivially_movable', 'is_throwing_move_copyable', 'is_unqualified_object', 'is_array_of_unqualified_object' and 'sizeof_t'. | |
5668 | + These type traits are added: 'is_affinity', 'are_affinity', 'is_in_affinity_types'. | |
5669 | + Additionally, type traits like 'is_extended_integer' are added to support 128-bit integers (see below). | |
5670 | + Some type traits are modified to support 128-bit integers (see below). | |
5671 | + Some traits are moved to 'unary_type_traits' Doxygen group since they have only one mandated template parameter and others are optional, which meets the unary type traits requirements in ISO C++. | |
5672 | + Some traits are revised and fixed. | |
5673 | + Type traits about trivility are reworked. | |
5674 | + The trait 'std::is_trivially_copyable' is used instead of the class template, which has different meaning. | |
5675 | + The was comment out in module YStandardEx.TypeOperation since build 245, due to the fact that libstdc++ from GCC 4.x had not implemented it (and other 'is_trivial_*' traits). | |
5676 | + This is available since GCC 5. | |
5677 | + The declaration of 'is_trivial_*' were once guarded by '!YB_IMPL_GNUC || YB_IMPL_GNUCPP >= 50000'. | |
5678 | + The minimum version requirement of GCC was then improved. The guards are removed in build 727 after these declarations being transferred to module YStandardEx.TypeTraits (but before to module YStandardEx.Meta in build 832). | |
5679 | + However, when other 'is_trivial_*' are already used, 'is_trivially_copyable' was omitted. | |
5680 | + The unary type trait with same name but different meaning was added to module YStandardEx.TypeOperation unfortunately then, since build 630. | |
5681 | + The differences are crucial. | |
5682 | + The standard one is weak as it does not care about the existence of the well-formed copy constriction and copy assignment. | |
5683 | + The class template defines one with strong assumptions of availablity of both well-formed trivial copy construction and trivial copy assignment. | |
5684 | + See https://www.foonathan.net/2021/03/trivially-copyable/. | |
5685 | + Now it has been fixed by using the standard trait. | |
5686 | + However, there are other issue for this trait in ISO C++. Notably, it has been changed since ISO C++17. | |
5687 | + See CWG 1734. | |
5688 | + This can have ABI compact and the results can be differ for classes with a deleted copy constructor. | |
5689 | + See https://bugs.llvm.org/show_bug.cgi?id=39050. | |
5690 | + The differences are not relying on at the code base. It is unspecified that 'ystdex::is_trivially_copyable' behaves with or without the change. | |
5691 | + The class template 'is_trivially_moveable' was introduced together with 'is_trivially_copyable'. | |
5692 | + This was the conterpart to 'is_trivially_copyable'. | |
5693 | + This is now removed, as there is no counterpart logically similar to 'std::is_trivially_copyable', and there is no actual use in the current code base. | |
5694 | + Names 'moveable' are replaced to 'movable' globally. | |
5695 | + This (only) affects on the traits names here. | |
5696 | + This excludes 'is_trivially_moveable' which is to be removed. | |
5697 | + The old names are not ungrammatical, but following modern and the ISO C++ parlance is better, and more importantly, more consistent (e.g. with 'ystdex::nonmovable' in module YStandardEx.Base). | |
5698 | + Both contemporary British and American English users may tend to use "movable" instead of "moveable". | |
5699 | + ISO C++ uses "movable" in its text, but no "moveable" at all. | |
5700 | + On the other hand, 'MakeMoveableGlobalMemory' in YFramework module YCLib.HostedGUI implementation is held, to be consistent with Win32 API name 'GMEM_MOVEABLE'. | |
5701 | + Unary type traits not respecting the fact that 'nullptr_t' can be a YStandardEx library type (rather than 'std::nullptr_t') are fixed. | |
5702 | + These include 'is_class', 'is_arithmetic', 'is_fundamental', 'is_scalar' and 'is_compound'. | |
5703 | + The order of declarations is adjusted. The declaration of 'is_null_pointer' is lifted before these traits to ease the implementation. | |
5704 | + Actually it is now just after 'is_void'. | |
5705 | + Support of integer types are improved. | |
5706 | + Support of 128-bit integer is opted in. | |
5707 | + The types '__int128' and 'unsigned __int128' are supported by GCC and Clang, and YFramework module NPL.NPLAMath has been already enabled it. | |
5708 | + See $2021-10 report.impl. | |
5709 | + They requires '__extension__' to prevent pedantic diagnostic with the compiler option '-Wpedantic' or '-pedantic-errors'. | |
5710 | + GCC still does not count them as extended integer types, even the compilers (gcc and g++) support all arithmetic operations supposed working on the extended integer types. | |
5711 | + See https://gcc.gnu.org/onlinedocs/gcc/Integers-implementation.html. | |
5712 | + This is far from ideal, but it works in practice. | |
5713 | + It has basically no issue in C besides not representable in 'intmax_t' and 'uintmax_t' for most platforms. | |
5714 | + This would be a problem for preprocessing phase evaluation (e.g. in '#if' directives). | |
5715 | + In fact the detection is a bit tricky in YBase module YDefinition for this reason, in particluar where <cstdint> cannot be used (so no portable macros can be used for '#if'). | |
5716 | + For C++ the standard library may need some additional works (see below). | |
5717 | + There are different issues around C++ standard library support (as extensions). | |
5718 | + See https://quuxplusone.github.io/blog/2019/02/28/is-int128-integral/. | |
5719 | + For some historical reasons, only GNU modes enables the support of 128-bit integers in libstdc++. | |
5720 | + See https://gcc.gnu.org/bugzilla/show_bug.cgi?id=40856. | |
5721 | + Actually libstdc++ adds additional specializations for strict standard modes when it is needed, see https://gcc.gnu.org/bugzilla/show_bug.cgi?id=96710. | |
5722 | + In some old days the <type_trait> support was missing also in GNU extension modes. | |
5723 | + It was fixed since GCC 4.7. See https://gcc.gnu.org/bugzilla/show_bug.cgi?id=50441. | |
5724 | + Since '__int128' is considered an extended integer type (hence an integral type) in libc++, it does not make much headache for implementation to adapt it. | |
5725 | + Support of type traits for 128-bit integers has been improved to work around the problems caused by these integers not treated extended integers. | |
5726 | + Now in YBase module YStandardEx.TypeInspection, the standard type traits concerned with 128-bit integer types are not simple declarations by 'using' when necessary. | |
5727 | + This is opted in when necessary, although the condition can be false positive. | |
5728 | + Having more alternative traits shall have no harm because the identities of the traits are not assumed at all, as per the rules for replacement interface in https://frankhb.github.io/YSLib-book/StandardUsing.en-US.html. | |
5729 | + The condition still works at the reasonaly best effort to be precise. | |
5730 | + Ideally no unnecessary alternatives are declared. | |
5731 | + This is better for translation-time performance. | |
5732 | + There is no '#undef' directive to undefine the internal macro to indicate the condition, so it can be used in other modules like YStandardEx.Meta. | |
5733 | + The condition to enable the alternative implementation with specializations integers in namespace 'ystdex' instead of 'using' declarations is based on the standard library implementations. | |
5734 | + When the condition is true, alternative implementation for type traits are used with the same name of their 'std' counterpart, despite in libstdc++ with standard modes they can be missing (while still conforming). | |
5735 | + These traits include 'is_integral', 'is_arithmetic', 'is_fundamental', 'is_scalar', 'is_coumpound', 'is_signed', 'is_unsigned', 'make_signed' and 'make_unsigned'. | |
5736 | + Support of 128-bit integers in libstdc++ denpends on the current mode being used. | |
5737 | + For GNU modes, additional features will be enabled, and there is no need to add more alternatives for type traits | |
5738 | + Though 'std::numeric_limits' still need additional work elsewhere (see below about 'ystdex::integer_width' for example). | |
5739 | + GCC < 5 is not supported here, so it is not tested in the conditon to work around the bug fixed before GCC 5. | |
5740 | + Support of 128-bit integers in libc++ is neutral to the standard modes. | |
5741 | + No configurations of 'defined(_LIBCPP_HAS_NO_INT128)' but '!__SIZEOF_INT128__' are supported, as it is always implied in <__config>. | |
5742 | + The condition only enables it for old implementations not guaranteed to have the feature. | |
5743 | + See https://reviews.llvm.org/D122351. | |
5744 | + ABI issues of extended integers are studied. | |
5745 | + See https://stackoverflow.com/questions/29927562 for actual ABI compatibility issues about extended integer types. | |
5746 | + It also reported Clang++ did not support any extended integer types and '__int128' is not treated extended integer types. This is not in https://clang.llvm.org/cxx_status.html now. | |
5747 | + Excluding 128-bit integers out of extended integer is concerned with 'intmax_t' and 'uintmax_t'. | |
5748 | + This is more about a specification issue, to avoiding the clash with 'intmax_t' and 'uintmax_t'. | |
5749 | + The 128-bit integers larger than 'std::intmax_t' is one of the infamous issue for C compatibiltiy. | |
5750 | + Even C++ can do better, nothing sensible are done by the vendors of the implementations. | |
5751 | + See https://thephd.dev/intmax_t-hell-c++-c. | |
5752 | + Nevertheless, if keeping things like 'intmax_t' away, it still can work. | |
5753 | + Clang at current supports '_ExtInt(N)' (and now deprecated in favor of ISO C23's '_BitInt(N)' types as extended integer types. | |
5754 | + See https://clang.llvm.org/docs/LanguageExtensions.html#id49. | |
5755 | + See https://blog.llvm.org/2020/04/the-new-clang-extint-feature-provides.html. | |
5756 | + This was proposed to ISO C and adopted. | |
5757 | + See WG14 N2768. | |
5758 | + See https://reviews.llvm.org/D108643. | |
5759 | + Technically they are named bit-precise integer types, rather than extended integer type. | |
5760 | + The maximum bit width varies. | |
5761 | + See https://releases.llvm.org/14.0.0/tools/clang/docs/ReleaseNotes.html#id13. | |
5762 | + See https://releases.llvm.org/16.0.0/tools/clang/docs/ReleaseNotes.html#id101. | |
5763 | + Additional types 'intmax_t' and 'uintmax_t' are introduced in namespace 'ystdex' to keep the assumptions at cost of ABI incompitibility (to 'std' ones). | |
5764 | + They are new so there is no ABI brakage with old code. | |
5765 | + Types provided by the GCC compiler frontend like '__GLIBCXX_TYPE_INT_N_0' are not used directly | |
5766 | + Though introduced for MSP430's '__int20' (see below), the type is just the 128-bit signed integer in some other platforms. | |
5767 | + Since there is currently no platform uses it other than 128-bit integer type and '__SIZEOF_INT128__' is sufficient to detect the type, this is not relied on. | |
5768 | + See also $2021-05 report.impl. | |
5769 | + Support of integers in module YStandardEx.CStandardInteger is enhanced. | |
5770 | + The addition of support for native 128-bit integers are taken into account. | |
5771 | + An additional fix is to support padding bits in the integer types. | |
5772 | + There may be some bugs in the implementation. | |
5773 | + See https://gcc.gnu.org/bugzilla/show_bug.cgi?id=97798 for example. | |
5774 | + The initial work for MSP430 with '__int20' did it correctly in the same time for the comilper frontend and libstdc++'s <limits>. | |
5775 | + This also includes '__GLIBCXX_TYPE_INT_N_0' and related changes, intialliy, not specific to 128-bit integer types. | |
5776 | + See https://gcc.gnu.org/git/gitweb.cgi?p=gcc.git;h=78a7c3172fe2e6cd959abb8bfc69f6b0dc747d49. | |
5777 | + Nevertheless, padding bits are only in 'bool'. There are no supported platform actually relies on the feature. | |
5778 | + There is no workaround for buggy implementations. Just use the underlying support. | |
5779 | + The unary type trait 'ystdex::integer_width' now correctly respects optional padding bits for types having the specialization of 'std::numeric_limits'. | |
5780 | + If there is the specialization, it shall be an interger type. This precondition is remained unchanged. Violation of the precondition is not checked. | |
5781 | + Otherwise, any integer type with value representation same to the object representation can be supported. | |
5782 | + That is, it has no padding bits in its object representation. | |
5783 | + In particular, '__int128' and 'unsigned __int128' may not have the 'std::numeric_limits' specialization for older version of libstdc++. | |
5784 | + See https://gcc.gnu.org/bugzilla/show_bug.cgi?id=96042. | |
5785 | + Since supported 128-bit integers have no padding bits, there is no need to add the 'std::numeric_limits' specializations for them even when the specializations do not exist. | |
5786 | + Traits 'extend_additive_overflow', 'extend_additive_underflow' and 'extend_product' are introduced to get the result type of arithmetic operations without overflow. | |
5787 | + They can help in cases where the usual arithmetic conversion rules in the core language resulting in a type not having sufficient range. | |
5788 | + In the case of potential arithmetic overflow, these traits lift the result to a floating-point type. | |
5789 | + The floating-point type is 'std::float_t' for maximum performance. | |
5790 | + It can be more efficient than using 'float', 'double' or 'long double' directly. | |
5791 | + See C99 Rationale: http://www.open-std.org/jtc1/sc22/wg14/www/C99RationaleV5.10.pdf. | |
5792 | + Actually for x87, native floating-point format in register is 80-bit, it suffers from conversion overhead to 'float' or 'double'. | |
5793 | + For compatiblity of memory representations and sakes of interoperations, 'float' and 'double' sticking to ISO/IEC/IEEE 60559 (IEEE-754) might be more appropriate. | |
5794 | + This need additional tweaks in the call sites since the purporse can not be judged here neutrally. | |
5795 | + Utilities for time in YStandardEx in YBase are improved. | |
5796 | + Support of types like ISO C++17's 'std::timespec' in metaprogramming has been added in module YStandardEx.CTime. | |
5797 | + A new header-only module Chrono extending the ISO C++'s <chorno> is added with direct replecement for ISO C++20's 'chrono::is_clock', checked cast interface and a bit more. | |
5798 | + The detailed implementation relying on further refactor and improvement of on YStandardEx headers (e.g. optional but robust 128-bit integer support). | |
5799 | + Some instances of 'std::duration_cast' are checked to see if it is appropriate to be replaced by 'ystdex::chrono::checked_duraion_cast'. | |
5800 | +Using of non-throwing interface of 'std::chrono::duration_values' is acknowledged in the whole project. | |
5801 | + This is neutral to WG21 P0972R0. | |
5802 | + Even without WG21 P0972R0 adoopted, the calls to 'max', 'min' and 'zero' have already been non-throwing as per the previous standard wording. | |
5803 | + Although mentioned in $2014-03 report.impl, 'duration_values' has never been used in this project. The type of 'noexcept' specifier has never been relied on, anyway. | |
5804 | + | |
5805 | +2024-04: | |
5806 | + | |
5807 | +report.impl: | |
5808 | +YBase improvement of numeric types continued. | |
5809 | + The workaround for old libstdc++ is added as a new header-only module LibDefect.Limits. | |
5810 | + This should be compatible to https://gcc.gnu.org/bugzilla/show_bug.cgi?id=96042. | |
5811 | + To be consistent, header inclusion <libdefect/limits.hpp> should replace <limits> in all use sites unless the added specializations are never used. | |
5812 | + Some are not subject to the change. | |
5813 | + The following modules do not require specializations of non-standard integer types because only specializations of known standard integers are used, so no changes are required: | |
5814 | + YBase modules HashTable, Memory, StringView and Tree in YStandardEx; | |
5815 | + Implementations of YFramework modules YCLib.Host, YCLib.YCommon and YSLib.UI.Loader; | |
5816 | + Implementation of YSTest module DSReader. | |
5817 | + YFramework module NPL.NPLAMath does not suuport the use on the 'std::numeric_limits' specializations for integer types. | |
5818 | + The diagnostics are to be improved for unsupported specializations. | |
5819 | + The implementation also does not use non-standard integers as the template argument of 'std::numeric_limits'. | |
5820 | + YBase module YStandardEx.Rational is depending on the change, but it transparent after the planned change in YBase module YStandardEx.CStandardInteger. | |
5821 | + Some need to be adjusted. | |
5822 | + YBase module YStandardEx.Chrono does not depend on the 'std::numeric_limits' specializations for non-standard integer types, but if instantiated, it would violate [temp.expl.spec]/7. | |
5823 | + Some need additional explicit header inclusion of <libdefect/limits.hpp> because they depended on the specializations without available explicitly included <limits> and the indirectly included headers are insufficient to guarntee <libdefect/limits.hpp> is included even after the planned changes here. | |
5824 | + YBase module YStandardEx.String ('ystdex::stoa') does depend on the specializations, and there is no explicit <limits> included (implied by module YStandardEx.StringView but not planned supporting the specializations). | |
5825 | + YBase module YStandardEx.Rational and YFramework module YSLib.Core.YCoreUtilites also have no explicit <limits> included. | |
5826 | + The remaining affected modules including explicit <limits> (to be changed to <libdefect/limits.hpp>) are: | |
5827 | + YBase modules Bit, Cast, CStandardInteger, CTime, Hash and List in YStandardEx. | |
5828 | + YFramework module YSLib.Core.YGDIBase. | |
5829 | + By specifying YStandardEx.CStandardInteger including <libdefect/limits.hpp>, some indirect dependencies can be implied and some are not needed to be adjusted any more. | |
5830 | + These include YBase modules YStandardEx.Chrono, YStandardEx.Hash and YStandardEx.Rational. | |
5831 | + Instead of <libdefect/limits.hpp>, YFramework module YSLib.Core.YCoreUtilites further needs <ystde/cstdint.hpp>. | |
5832 | + The redundant header inclusion <limits> (if any) can be removed later. | |
5833 | + However, new headers may include YStandardEx.CStandardInteger, see below. | |
5834 | + A new header-only module YStandardEx.Limits is added. | |
5835 | + This encapsulate the newly added YBase module LibDefect.Limits with some additional traits. | |
5836 | + This also addresses the problem that no appropriate place is in YBase for traits not specific to integer types (which are previously added to YStandardEx.CStandardInteger). | |
5837 | + This header can sometimes replace <libdefect/limits.hpp>. | |
5838 | + A new header-only module YStandardEx.Arithmetic is added. | |
5839 | + Integer arithmetics aware of overflow (and underflow) are added here rather than in YStandardEx.CStandardInteger. | |
5840 | + The module YStandardEx.Chrono is adjusted to use the implementation here. | |
5841 | + Bugs of lacking of SFINAE-friend in some member functions in iterators in YBase module YStandardEx.Iterator have been fixed. | |
5842 | + The bug affects iterator adaptors supporting a wider range of operations than the adapted iterators. | |
5843 | + If some adapted iterator type does not support specific operations, the adaptor should not assume they are available unless the iterator requirements (or iterator concepts since ISO C++20) guarantees they must exist. | |
5844 | + Ill-formed expressions implied by the instantiation in the noexcept-specificiation shall be prevented even when the underlying iterator does not have the required operations. | |
5845 | + Such bugs may affect the well-formedness without invoking the operations. | |
5846 | + The bug on 'operator-' of 'ystdex::transformed_iterator' would cause an iterator not satisfying 'RandomAccessIterator' concept failed at 'iter_difference' check in ISO C++20 modes, at least with Clang++ 17 and libc++. | |
5847 | + A new module YStandardEx.CharacterConversion is added. | |
5848 | + As ISO C++17's <charconv>, this is to support primitive numeric conversions. | |
5849 | + As suggested by its name, this should extend <charconv>, but not at current. | |
5850 | + This is currently header-only. | |
5851 | + In particular, conversions from internal representations of external representations of numeric values are supported here, as the basis for other headers. | |
5852 | + This is like the case that the standard header <format> (ISO C++20 onwards) can share some implementation from <charconv>. | |
5853 | + This provides underlying implementation of integer 'to_string' conversions for the module YStandard.String (see below). | |
5854 | + The interface is actually a generalized form of numeric conversions in the implementation of YFramework module NPL.NPLAMath. | |
5855 | + The module NPL.NPLAMath is to be simplified by reusing these interface. | |
5856 | + Conversion functions 'ystdex::to_string' in module YStandardEx.String are improved. | |
5857 | + The overloads to support 128-bit integers (if any), as well as overloads with allocator support, are added. | |
5858 | + The implementation now uses the underlying implementation from the module YStandardEx.CharacterConversion. | |
5859 | + All the standard implementations of 'std::to_string' for integers are replaced. | |
5860 | + The overloads for integer parameters to replace 'std::to_string' and the overloads with allocator support share the underlying code. | |
5861 | + This is different to other replacement features which use the existing standard library implementation as possible unless it is not available under the current standard mode or there are conforming bugs. | |
5862 | + This prevents the inconsistency between any 'std::to_string' implementations and additional overloads (e.g. due to bugs). | |
5863 | + This also prevent some code bloat by different code paths when these overloads are used together via 'ystdex::to_string', albeit not when 'std::to_string' is used explicitly. | |
5864 | + This should also be more efficient than a loop of division 10 (as in Microsft STL) filling the buffer backwards. | |
5865 | + By including <ystdex/charconv.h>, there is no needed to explicitly include <libdefect/limits.hpp>. | |
5866 | + There is no need to include <libdefect/limits.h> separatedly in module YStandardEx.String. | |
5867 | + | |
5661 | 5868 | //// |
5662 | 5869 |
@@ -1,23 +1,22 @@ | ||
1 | 1 | /* |
2 | - © 2012-2023 FrankHB. | |
2 | + © 2012-2024 FrankHB. | |
3 | 3 | |
4 | - This file is part of the YSLib project, and may only be used, | |
5 | - modified, and distributed under the terms of the YSLib project | |
6 | - license, LICENSE.TXT. By continuing to use, modify, or distribute | |
7 | - this file you indicate that you have read the license and | |
8 | - understand and accept it fully. | |
4 | + This file is part of the YSLib project, and may only be used, modified, | |
5 | + and distributed under the terms of the YSLib project license. | |
6 | + By continuing to use, modify, or distribute this file you indicate that | |
7 | + you have read the license and understand and accept it fully. | |
9 | 8 | */ |
10 | 9 | |
11 | 10 | /*! \file YBase.txt |
12 | 11 | \ingroup Documentation |
13 | 12 | \brief YBase 说明。 |
14 | -\version r2063 | |
13 | +\version r2180 | |
15 | 14 | \author FrankHB <frankhb1989@gmail.com> |
16 | 15 | \since build 305 |
17 | 16 | \par 创建时间: |
18 | 17 | 2012-04-29 17:11:42 +0800 |
19 | 18 | \par 修改时间: |
20 | - 2023-02-20 19:21 +0800 | |
19 | + 2024-04-14 22:06 +0800 | |
21 | 20 | \par 文本编码: |
22 | 21 | UTF-8 |
23 | 22 | \par 模块名称: |
@@ -74,9 +73,12 @@ | ||
74 | 73 | 尽可能严格遵守 ISO C++ ,涉及未指定行为和实现定义的行为时应由文档说明。 |
75 | 74 | 特性使用的基本规则参见 [Documentation::ProjectRules @@1.3.1] ,应符合其中的基准实现要求。 |
76 | 75 | 据此,语言特性指定保持以下原则: |
77 | -默认使用 ISO C++11 的一个严格子集; | |
78 | -可选使用之后版本的标准兼容的特性; | |
79 | -使用的特性应使代码保持和已出版的最新标准兼容。 | |
76 | + 默认使用 ISO C++11 的一个严格子集。 | |
77 | + 可选使用之后版本的标准兼容的特性。 | |
78 | + 使用的特性应使代码保持和已出版的最新标准兼容。 | |
79 | + 仅在必要时非标准的特定实现的公开特性,这些特性被实现使用或包装为兼容支持的平台的接口。 | |
80 | + **注释** 为检查特性可用性,可能依赖使用特定实现的公开接口(如实现相关的宏定义)。 | |
81 | + **注释** 详见扩展特性(@2.1.1.2) 。 | |
80 | 82 | 可选使用的标准兼容的特性可用于支持对 ISO C++ 自身可能具有的缺陷的修正。 |
81 | 83 | 除使用标准库明确依赖多线程环境的接口外,YBase 严格不依赖运行时具有的多线程执行环境。 |
82 | 84 | 在 YDefinition 和 YStandardEx 提供标准库替代接口时,视语义在被 ISO C++ 允许(这是一般情形)的前提下可提供更多的 [[nodiscard]](以 YB_ATTR_nodiscard 的形式)和 noexcept(以 ynothrow 等形式)的异常规范。 |
@@ -85,6 +87,7 @@ | ||
85 | 87 | 关于对语言的使用,另见 [Documentation::LanguageConvention @@5] 和 [Documentation::LanguageConvention @@6] 。 |
86 | 88 | |
87 | 89 | @2.1.1.1 预处理指令: |
90 | +除非另行指定,头文件包含同库使用约定([Documentation::CommonRules @@3.13.2]) 。 | |
88 | 91 | 允许在预处理指令中使用特定实现的宏检查支持的特性作为变通。 |
89 | 92 | 正式的变通使用的宏仅限公开支持的宏或者 YDefinition 提供的宏。 |
90 | 93 | 其中,在条件包含中可使用除符合 ISO C++ 当前草案的 __has_cpp_attribute 和 __has_include 外,还可使用由 https://clang.llvm.org/docs/LanguageExtensions.html 约定含义的以下特性检查扩展: |
@@ -99,12 +102,14 @@ | ||
99 | 102 | @2.1.1.2 内建和扩展特性: |
100 | 103 | 若内建特性在 YDefinition 提供宏支持且可用,以 YDefinition 宏替代直接的使用。 |
101 | 104 | 假定可能支持的特性(除非另行指定,按 https://clang.llvm.org/docs/LanguageExtensions.html 约定含义 )在本节列出。 |
105 | +使用 __extension__ 标注支持 GNU 扩展以支持在严格标准模式下使用: | |
106 | + __int128 和 __uint128 类型。 | |
102 | 107 | 使用 Microsoft VC++ 支持的 #pragma intrinsic 引入的内建特性: |
103 | 108 | _BitScanForward |
104 | 109 | _BitScanForward64 |
105 | 110 | _BitScanReverse |
106 | 111 | _BitScanReverse64 |
107 | -使用以下可用 __has_builtin 检查的内建特性(返回为 true ): | |
112 | +使用以下可用 __has_builtin 检查的内建特性(支持时返回非零值): | |
108 | 113 | __builtin_addressof |
109 | 114 | __builtin_assume |
110 | 115 | __builtin_assume_aligned |
@@ -115,14 +120,20 @@ | ||
115 | 120 | __builtin_ctzl |
116 | 121 | __builtin_ctzll |
117 | 122 | __builtin_expect |
123 | +__builtin_add_overflow | |
124 | +__builtin_mul_overflow | |
125 | +__builtin_sub_overflow | |
118 | 126 | __builtin_trap |
119 | 127 | __builtin_unreachable |
128 | +__remove_cvref | |
120 | 129 | 在特定实现还可能使用以下可用 __has_builtin 检查的内建特性: |
121 | 130 | __builtin_constant_p |
122 | 131 | __builtin_ia32_bsrdi |
123 | 132 | __builtin_ia32_bsrsi |
124 | 133 | 使用以下可用 __has_extension 检查的扩展特性(返回为 true ): |
125 | 134 | __is_final |
135 | +特定实现使用以下特性: | |
136 | +__integer_pack | |
126 | 137 | 外部参考列表: |
127 | 138 | https://docs.microsoft.com/en-us/cpp/intrinsics/bitscanforward-bitscanforward64 |
128 | 139 | https://docs.microsoft.com/en-us/cpp/intrinsics/bitscanreverse-bitscanreverse64 |
@@ -170,7 +181,7 @@ | ||
170 | 181 | 当前这些替代实现包括: |
171 | 182 | YStandardEx::Bit(@2.5.7.6) 使用 GCC 时,对 i386 和 x86_64 的部分实现使用特定体系结构的替代实现,以避免代码生成的性能缺陷。 |
172 | 183 | 参见 https://gcc.gnu.org/bugzilla/show_bug.cgi?id=29776 。 |
173 | - 替代实现优先检查可使用的 GCC 内建特性(@2.1.1.2) ;否则,使用内联汇编。 | |
184 | + 替代实现优先检查可使用的 GCC 内建特性(@2.1.1.2) ;否则,使用内联汇编。 | |
174 | 185 | |
175 | 186 | @2.1.2 安全性: |
176 | 187 | 基本内容参见 [Documentation::CommonRules @@3.11] 。另见 @2.1.1 。 |
@@ -247,6 +258,7 @@ | ||
247 | 258 | YDefinition 在 @2.1.1 的基础上支持更多实现,且提供特定 ISO C++11 关键字的替代。 |
248 | 259 | YDefinition 中的特性应保证在被替代的关键字不被支持时仍可以被实现接受。 |
249 | 260 | 文件內容为系统环境和公用类型和宏的基础定义,包括对实现环境的检测、实现特性的封装、部分未被实现关键字替代以及一些语言层次上的公共基础设施。 |
261 | +因为提供对实现环境的选项(例如消除 Microsoft Visual C++ 的标准库警告的宏定义),直接或间接包含这个头文件时一般应保证置于其它标准库头的包含之前(关于头文件顺序,另见 [Documentation::CommonRules @@3.13.2.2] )。 | |
250 | 262 | 以下名称以 y 起始的宏是表达式宏([Documentation::CommonRules @@5.10]) 或替代关键字(@2.4.7) 。 |
251 | 263 | |
252 | 264 | @2.4.1 实现标记宏: |
@@ -334,9 +346,11 @@ | ||
334 | 346 | "tuple.hpp" 依赖 "apply.hpp" ; |
335 | 347 | "memory.hpp" 依赖 "pointer.hpp" 和 "allocator.hpp" ; |
336 | 348 | "functional.hpp" 依赖 "invoke.hpp" 、"ref.hpp" 、"functor.hpp" 、"bind.hpp" 、"function.hpp" 和 "hash.hpp"; |
349 | +"string.hpp" 依赖 <libdefect/string.h> ; | |
337 | 350 | "string.hpp" 、"array.hpp" 、"string_view" 、"list.hpp" 、"map.hpp" 和 "set.hpp" 依赖 "range.hpp" ; |
338 | 351 | "iterator.hpp" 依赖 "iterator_op.hpp" 。 |
339 | 352 | 因其它接口设计原因,以下依赖性作为接口公开: |
353 | +"integral_constant.hpp" 依赖 "cstddef.h" ; | |
340 | 354 | "type_inspection.hpp" 依赖 "integral_constant.hpp" ; |
341 | 355 | "meta.hpp" 依赖 "type_inspection.hpp" ; |
342 | 356 | "variadic.hpp" 和 "invoke.hpp" 依赖 "meta.hpp" ; |
@@ -344,26 +358,31 @@ | ||
344 | 358 | "iterator_op.hpp" 依赖 "operators.hpp" ; |
345 | 359 | "placement.hpp" 、"range.hpp" 和 "operators.hpp" 依赖 "addressof.hpp" ; |
346 | 360 | "pointer.hpp" 和 "memory.hpp" 依赖 "iterator_op.hpp" ; |
361 | +"cstdint.hpp" 、"charconv.h" 和 "chrono.hpp" 依赖 <libdefect/limits.hpp> ; | |
347 | 362 | "apply.hpp" 依赖 "invoke.hpp" ; |
348 | 363 | "string_view.hpp" 依赖 <libdefect/string.h> ; |
349 | 364 | "hash.hpp" 和 "mixin.hpp" 依赖 "tuple.hpp" ; |
350 | 365 | "functor.hpp" 依赖 "ref.hpp" 和 "type_traits.hpp" ; |
351 | 366 | "function_adaptor.hpp" 依赖 "bind.hpp" 和 "compose.hpp" ; |
352 | 367 | "functional.hpp" 依赖 "function_adaptor.hpp" 和 "expanded_function.hpp" ; |
368 | +"arithmetic.hpp" 依赖 "cstdint.hpp" 、"limits.hpp" 、<cmath> 和 "exception.h" ; | |
353 | 369 | "tree.h" 、"hash_table.h" 、"container.hpp" 、"flat_map.hpp" 和 "flat_set.hpp" 依赖 "range.hpp" ; |
354 | -"tree.h" 和 "hash_table.h" 依赖 "node_handle.hpp" ; | |
370 | +"tree.h" 和 "hash_table.h" 依赖 "node_handle.hpp" ; | |
355 | 371 | "hash_table.h" 依赖 "hash.hpp" ; |
356 | -"string.hpp" 依赖 "container.hpp" ; | |
372 | +"string.hpp" 依赖 "container.hpp" 和 "charconv.h" ; | |
357 | 373 | "list.hpp" 依赖 "node_base.h" 。 |
358 | 374 | "map.hpp" 和 "set.hpp" 依赖 "tree.h" ; |
359 | 375 | "unordered_map.hpp" 和 "unordered_set.hpp" 依赖 "hash_table.h" ; |
360 | 376 | "any_iterator.hpp" 依赖 "any.h" 。 |
361 | -另见 @2.5.4 和以下各节。 | |
377 | +另见不依赖其它 YStandardEx 文件的基本头文件(@2.5.4) 和以下各节。 | |
378 | +**原理** | |
379 | +因为接口设计公开依赖的常见情形是接口使用类型具有依赖,需要确保使用前引入适当的声明。 | |
362 | 380 | **注释** |
363 | 381 | "range.hpp" 被多个容器相关的头文件公开依赖,类似 ISO C++ [iterator.range]/1 对 <iterator> 外的多个标准库头提供自定义范围访问的约定。 |
364 | 382 | |
365 | 383 | @2.5.1.2 内部头文件依赖性: |
366 | -除对标准库头的公开依赖外,当前实现保持以下内部直接依赖(及通过传递闭包蕴含实现的公开依赖)供实现参考,可简化头文件包含和避免循环引用: | |
384 | +除对标准库头的公开依赖外,当前实现保持以下内部直接依赖(及通过传递闭包蕴含实现的公开依赖)供 YBase 实现参考,可简化头文件包含和避免循环引用: | |
385 | +"integral_constant.hpp" 依赖 "cstddef.h" ; | |
367 | 386 | "type_inspection.hpp" 依赖 "integral_constant.hpp" ; |
368 | 387 | "meta.hpp" 依赖 "type_inspection.hpp" ; |
369 | 388 | "variadic.hpp" 和 "invoke.hpp" 依赖 "meta.hpp" ; |
@@ -384,6 +403,7 @@ | ||
384 | 403 | "apply.hpp" 依赖 "invoke.hpp" ; |
385 | 404 | "tuple.hpp" 依赖 "apply.hpp" ; |
386 | 405 | "pointer.hpp" 依赖 "iterator_op.hpp" ; |
406 | +"cstdint.hpp" 、"charconv.h" 和 "chrono.hpp" 内部依赖 "limits.hpp"(蕴含公开依赖 <libdefect/limits.hpp> ); | |
387 | 407 | "allocator.hpp" 内部依赖 "type_op.hpp" 和 "pointer.hpp" ; |
388 | 408 | "memory.hpp" 依赖 "pointer.hpp" 和 "allocator.hpp" ; |
389 | 409 | "memory.hpp" 内部依赖 "placement.hpp" 和 "ref.hpp" ; |
@@ -398,6 +418,7 @@ | ||
398 | 418 | "expanded_function.hpp" 内部依赖 "function.hpp" ; |
399 | 419 | "functional.hpp" 依赖 "invoke.hpp" 、"ref.hpp" 、"functor.hpp" 、"bind.hpp" 、"function.hpp" 、"hash.hpp" 、"function_adaptor.hpp" 和 "expanded_function.hpp" ; |
400 | 420 | "any.h" 内部依赖 "typeinfo.h" 和 "utility.hpp" ; |
421 | +"arithmetic.hpp" 依赖 "cstdint.hpp" 和 "limits.hpp" ; | |
401 | 422 | "iterator.hpp" 依赖 "iterator_op.hpp" ; |
402 | 423 | "iterator.hpp" 内部依赖 "ref.hpp" ; |
403 | 424 | "string_view.hpp" 依赖 "range.hpp" ; |
@@ -408,20 +429,27 @@ | ||
408 | 429 | "container.hpp" 依赖 "range.hpp" ; |
409 | 430 | "container.hpp" 内部依赖 "integer_sequence.hpp" ; |
410 | 431 | "any_iterator.hpp" 依赖 "any.h" ; |
411 | -"string.hpp" 依赖 "container.hpp" ; | |
412 | -"string.hpp" 内部依赖 "allocator.hpp" 和 "string_view.hpp"(蕴含公开依赖 "range.hpp" ); | |
432 | +"string.hpp" 依赖 "container.hpp" 和 "charconv.h" ; | |
433 | +"string.hpp" 内部依赖 "allocator.hpp" 和 "string_view.hpp"(蕴含公开依赖 "range.hpp" 和 <libdefect/string.h> ); | |
413 | 434 | "list.hpp" 依赖 "range.hpp" ; |
414 | 435 | "map.hpp" 和 "set.hpp" 依赖 "tree.h"(蕴含公开依赖 "range.hpp" ); |
415 | 436 | "unordered_map.hpp" 和 "unordered_set.hpp" 依赖 "hash_table.h"(蕴含公开依赖 "range.hpp" ); |
416 | 437 | "flat_map.hpp" 和 "flat_set.hpp" 依赖 "range.hpp" ; |
417 | 438 | "scope_guard.hpp" 内部依赖 "function.hpp" 。 |
418 | 439 | 除此之外,内部依赖对标准库头的依赖也视为内部依赖。 |
440 | +**注释** 内部依赖可能在未来改变而不视为接口变更。YBase 外的实现应避免假定具体的内部依赖存在。 | |
419 | 441 | |
420 | 442 | @2.5.2 命名空间和模板特化: |
421 | -除在块作用域、非公开的实现命名空间和此处列明的例外,禁止其它的别名声明引入 std 成员命名空间: | |
422 | -ystdex 中对标准库的元编程和类型特征名称使用别名声明; | |
423 | -文档指定的以实现为 ADL([Documentation::LanguageConvention @@5.2.4.1]) 提供并行重载为目的的别名声明。 | |
443 | +除在块作用域、非公开的实现命名空间和此处指定的例外,禁止其它的别名声明引入 std 成员命名空间: | |
444 | + ystdex 中对标准库的元编程和类型特征名称使用别名声明。 | |
445 | + 文档指定的以实现为 ADL([Documentation::LanguageConvention @@5.2.4.1]) 提供并行重载为目的的别名声明。 | |
424 | 446 | ystdex 的类型在声明所在的同一头文件中,可能存在 std 命名空间中的类模板的对应特化。 |
447 | +**注释** 以下类似 ISO C++ [namespace.std] ;变量模板没有被当前实现依赖。 | |
448 | +除非另行指定,在公开命名空间(@2.5.2.2) 中添加声明,程序的行为未定义。 | |
449 | +除非显式禁止,当满足以下条件时,程序可为公开命名空间中的类模板添加模板特化: | |
450 | + 添加的声明至少依赖一个程序定义的(program-defined) 类型。 | |
451 | + 特化满足被特化模板的原始要求。 | |
452 | +除非另行指定,声明显式或偏特化变量模板的程序的行为未定义。 | |
425 | 453 | |
426 | 454 | @2.5.2.1 非公开实现命名空间: |
427 | 455 | 命名空间 ystdex 内 details 命名空间和声明以宏 yimpl(@2.4.3) 修饰的命名空间保留为非公开实现。 |
@@ -434,6 +462,9 @@ | ||
434 | 462 | ystdex :YStandardEx 使用的默认命名空间。 |
435 | 463 | ystdex::any_ops :ystdex::any 相关的底层操作接口。 |
436 | 464 | ystdex::bases :隔离 ADL 的基类命名空间。 |
465 | +ystdex::chrono :替代 std::chrono 的命名空间。 | |
466 | +inline ystdex::chrono::cpp2011 包含 ISO C++ 2011 引入的 std::chrono 名称或更新实体特性的命名空间。 | |
467 | +inline ystdex::chrono::cpp2020 包含 ISO C++ 2020 引入的 std::chrono 名称或更新实体特性的命名空间。 | |
437 | 468 | inline ystdex::cpp2011 包含 ISO C++ 2011 引入的 std 名称或更新实体特性的命名空间。 |
438 | 469 | inline ystdex::cpp2014 包含 ISO C++ 2014 引入的 std 名称或更新实体特性的命名空间。 |
439 | 470 | inline ystdex::cpp2017 包含 ISO C++ 2017 引入的 std 名称或更新实体特性的命名空间。 |
@@ -442,7 +473,7 @@ | ||
442 | 473 | ystdex::fseq :变长序列函数模板操作。 |
443 | 474 | ystdex::nodep :隔离 ADL 的基类以外的命名空间。 |
444 | 475 | ystdex::pmr :替代 std::pmr 的命名空间。 |
445 | -inline ystdex::pmr::cpp2017 :包含 ISO C++ 2017 引入的 std::pmr 名称的命名空间。 | |
476 | +inline ystdex::pmr::cpp2017 :包含 ISO C++ 2017 引入的 std::pmr 名称或更新实体特性的命名空间。 | |
446 | 477 | ystdex::threading :线程相关操作。 |
447 | 478 | ystdex::uniformed_tags :对非模板和不同模板参数相同的类型标签接口。 |
448 | 479 | ystdex::vseq :变长序列元函数操作。 |
@@ -467,6 +498,7 @@ | ||
467 | 498 | 不以别名声明时,为不同实体,同时使用(如作为重载函数的参数)时需要分别处理,避免违反 ODR([Documentation::LanguageConvention @@5.1.8]) ; |
468 | 499 | 不保证变更接口时会不在上述类别之间迁移。 |
469 | 500 | 除非文档说明,保证使用 YStandard 接口可替换标准库接口或 TS 接口,但不保证逆向替换可行( YStandardEx 可扩展标准库中不具备的特性)。 |
501 | +部分头文件对标准库提供扩展或替代。这些扩展和替代被分组,以下描述中每一节对应一个分组。除非存在包含依赖要求,每组内同被扩展和替代或接口在标准文档中相同的章节顺序。 | |
470 | 502 | 以下文档概要仅包括头文件没有详细明确的部分。 |
471 | 503 | |
472 | 504 | @2.5.4 不依赖其它 YStandardEx 文件的基本头文件: |
@@ -477,7 +509,8 @@ | ||
477 | 509 | |
478 | 510 | @2.5.5 基本 ISO C 标准库扩展: |
479 | 511 | 提供 ISO C 标准库的扩展,可能具有实现文件。 |
480 | -头文件和实现文件的头文件依赖要求同 @2.5.4 。 | |
512 | +头文件和实现文件的头文件依赖要求同不依赖其它 YStandardEx 文件的基本头文件(@2.5.4) 。 | |
513 | +**注释** 不满足此要求的 ISO C 标准库扩展可能作为以下的 ISO C++ 标准库扩展的一部分。 | |
481 | 514 | |
482 | 515 | @2.5.5.1 ISO C 标准库类型定义扩展 CStandardDefinition : |
483 | 516 | 头文件扩展标准库头 <cstddef> ,提供一些替代实现。 |
@@ -525,7 +558,7 @@ | ||
525 | 558 | |
526 | 559 | @2.5.7 核心扩展库: |
527 | 560 | 用于构建其它库的通用元编程以外的设施。 |
528 | -依赖规则同 @2.5.6 。 | |
561 | +依赖规则同通用元编程库(@2.5.6) 。 | |
529 | 562 | |
530 | 563 | @2.5.7.1 解引用操作 DereferenceOperation : |
531 | 564 | 提供解引用操作检查的模板,作为迭代器操作的基础。 |
@@ -572,20 +605,21 @@ | ||
572 | 605 | 以下头文件扩展 ISO C++ 标准定义的语言支持库([support.general]) 中的至少一个并可能扩展其它标准库头,提供对应的相似接口,不依赖以上文件外的 YStandardEx 头文件。 |
573 | 606 | |
574 | 607 | @2.5.8.1 ISO C 标准整数类型操作 CStandardInteger : |
575 | -头文件间接扩展标准库头 <cstdint> ,提供一些类型操作和一些整数类型的模板特化以及模算术的基本支持。 | |
608 | +间接扩展标准库头 <cstdint> ,提供一些类型操作和一些整数类型的模板特化以及模算术的基本支持。 | |
576 | 609 | |
577 | -@2.5.8.2 标准库异常扩展接口 Exception : | |
578 | -扩展标准库头 <exception> 、<stdexcept> 和 <system_error> ,提供便利接口和若干异常基类。 | |
610 | +@2.5.8.2 实现限制 Limits : | |
611 | +扩展标准库头 <limits> ,提供一些扩展的特征和元编程设施。 | |
579 | 612 | |
580 | 613 | @2.5.8.3 ISO C++ 类型信息扩展 TypeInfo : |
581 | 614 | 头文件扩展标准库头 <typeinfo> ,提供了无 RTTI 开销的静态类型信息类和兼容接口。 |
582 | 615 | |
583 | -@2.5.8.4 ISO C++ 类型信息扩展 TypeIndex : | |
584 | -头文件扩展标准库头 <typeindex> ,提供了无 RTTI 开销的静态类型索引类和兼容接口。 | |
616 | +@2.5.8.4 标准库异常扩展接口 Exception : | |
617 | +扩展标准库头 <exception> 、<stdexcept> 和 <system_error> ,提供便利接口和若干异常基类。 | |
585 | 618 | |
586 | 619 | @2.5.9 基本 ISO C++ 标准库扩展和替代: |
587 | -扩展或替代标准库文件,提供和标准库对应的相似接口,但不包含基本 ISO C 标准库扩展(@2.5.5) 和 ISO C++ 标准库字符串和模板库组件扩展和替代(@2.5.9) 。 | |
588 | -除 @2.5.1.2 外,不依赖之前提及以外的 YStandardEx 头文件。 | |
620 | +扩展或替代标准库文件或作为这些头文件依赖的接口的一部分,提供和标准库对应的相似接口,但不包含基本 ISO C 标准库扩展(@2.5.5) 和 ISO C++ 标准库字符串和模板库组件扩展和替代(@2.5.9) 。 | |
621 | +ISO C++ 标准库字符串和模板库组件扩展和替代可能依赖的 ISO C 标准库扩展在此视为基本 ISO C++ 标准库扩展。 | |
622 | +除指定依赖的头文件(@2.5.1.2) 外,不依赖之前提及以外的 YStandardEx 头文件。 | |
589 | 623 | |
590 | 624 | @2.5.9.1 ISO C++ 类型特征扩展 TypeTraits : |
591 | 625 | 间接扩展标准库头 <type_traits> ,包括元编程设施等。 |
@@ -617,7 +651,8 @@ | ||
617 | 651 | 相对地,ystdex::pmr::new_delete_resource 蕴含的 ystdex::pmr::new_delete_resource_t 类型被作为公开接口直接提供。若有必要,用户可在每个翻译单元中定义和使用单独的资源对象,以避免潜在的生存期问题。 |
618 | 652 | 但是因为没有使用 nifty counter 等方式定义在头文件,用户仍应确保跨翻译单元的资源初始化和释放顺序符合预期而避免未定义行为。 |
619 | 653 | |
620 | -@2.5.9.9 ISO C 标准字符串扩展 CString | |
654 | +@2.5.9.9 ISO C 标准字符串扩展 CString : | |
655 | +扩展标准库头 <cstring> 。 | |
621 | 656 | |
622 | 657 | @2.5.9.10 只读字符串视图 StringView : |
623 | 658 | 提供 ISO C++17 标准库头 <string_view> 的替代接口和实现。 |
@@ -643,20 +678,31 @@ | ||
643 | 678 | @2.5.9.17 展开调用的函数对象 ExpandedFunction : |
644 | 679 | 提供通用的允许实际参数列表的后缀在调用时被忽略的调用接口和对应的调用包装。 |
645 | 680 | |
646 | -@2.5.9.18 函数和可调用对象 Functional : | |
647 | -扩展标准库头 <functional> ,提供函数类型操作和各种一般调用的实现。 | |
648 | - | |
649 | -@2.5.9.19 可选对象类型 Optional : | |
681 | +@2.5.9.18 可选对象类型 Optional : | |
650 | 682 | 提供 ISO C++17 标准库头 <optional> 的替代接口和实现,并提供一些扩展。 |
651 | 683 | |
652 | -@2.5.9.20 动态泛型类型 Any : | |
684 | +@2.5.9.19 动态泛型类型 Any : | |
653 | 685 | 主要提供 Boost.Any 和提议的 ISO C++ std::experiment::any 的类似的基于类型擦除实现的用于保存运行时确定类型的值的对象,默认使用和 libstdc++ 5 类似的小对象优化实现。 |
654 | 686 | 命名空间 any_ops 提供更多可供用户调整的内部接口。 |
655 | 687 | 提供了一些其它不和 any 类直接相关的类型擦除接口。 |
656 | 688 | 使用非零宏 YB_Use_LightweightTypeID 指定不依赖 RTTI 的 type_info 。 |
657 | 689 | |
690 | +@2.5.9.20 函数和可调用对象 Functional : | |
691 | +扩展标准库头 <functional> ,提供函数类型操作和各种一般调用的实现。 | |
692 | + | |
693 | +@2.5.9.21 ISO C++ 类型信息扩展 TypeIndex : | |
694 | +头文件扩展标准库头 <typeindex> ,提供了无 RTTI 开销的静态类型索引类和兼容接口。 | |
695 | + | |
696 | +@2.5.9.22 算术类型和操作 Arithmetic : | |
697 | +提供基于 CStandardInteger(@2.5.8.1) 和 Limits(@2.5.8.2) 的算术类型和操作。 | |
698 | + | |
699 | +@2.5.9.23 数值的字符表示和转换操作 CharacterConversion : | |
700 | +提供数值字符表示和转换操作。 | |
701 | +提供类似 ISO C++23 <charconv> 的部分功能,但当前没有扩展 <charconv> 。这可能会在以后改变。 | |
702 | + | |
658 | 703 | @2.5.10 ISO C++ 标准库字符串和模板库组件扩展和替代: |
659 | -同 @2.5.9 ,直接或间接扩展字符串、<iterator> 、<algorithm> 、容器、流或并发 API 的头文件,或提供这些头文件的内部实现基础。 | |
704 | +同基本 ISO C++ 标准库扩展和替代(@2.5.9) ,直接或间接扩展字符串、容器、迭代器、算法、流或并发 API 的头文件,或提供这些头文件的内部实现基础。 | |
705 | +**注释** 因为依赖性,部分扩展出现的顺序和标准文档中描述的顺序(@2.5.3) 不同。 | |
660 | 706 | |
661 | 707 | @2.5.10.1 通用迭代器 Iterator : |
662 | 708 | 间接扩展标准库头 <iterator> ,提供若干迭代器适配器和相关操作。 |
@@ -668,75 +714,85 @@ | ||
668 | 714 | 扩展标准库头 <algorithm> ,提供一些泛型算法。 |
669 | 715 | 除非另行指定,使用 first 和 last 为名称的参数指定同一个范围,否则不保证结果正确,可能引起未定义行为。 |
670 | 716 | |
671 | -@2.5.10.4 ISO C++ 标准字符串扩展 String : | |
717 | +@2.5.10.4 通用容器操作 Container : | |
718 | +实现通用容器适配器模板和对容器类型及构建数组容器的操作。 | |
719 | +参数限制同 Algorithm(@2.5.10.3) 。 | |
720 | + | |
721 | +@2.5.10.5 ISO C++ 标准字符串扩展 String : | |
672 | 722 | 间接扩展标准库头 <string> ,提供 std::char_traits 的扩展功能和对 std::basic_string 及类似类型的操作。 |
673 | 723 | |
674 | -@2.5.10.5 指定结束字符的只读字符串视图 TStringView : | |
724 | +@2.5.10.6 指定结束字符的只读字符串视图 TStringView : | |
675 | 725 | 基于 StringView(@2.5.9.10) 提供近似标准库头 <string_view> 中的 string_view 的扩展类型。 |
676 | 726 | |
677 | -@2.5.10.6 数组操作 Array : | |
727 | +@2.5.10.7 数组操作 Array : | |
678 | 728 | 扩展标准库头 <array> ,提供内建数组和 std::array 相关类型的操作。 |
679 | 729 | |
680 | -@2.5.10.7 作为节点序列容器实现的节点基础 NodeBase : | |
730 | +@2.5.10.8 作为节点序列容器实现的节点基础 NodeBase : | |
681 | 731 | 提供一些例程用于作为基于节点的序列容器实现的基础。 |
682 | 732 | 当前暂时不公开 API ,但其中的 API 已被 List(@2.5.10.8) 中的容器二进制依赖。未来可能会提供基于节点实现关联容器公共 API 。 |
683 | 733 | |
684 | -@2.5.10.8 列表容器 List : | |
734 | +@2.5.10.9 列表容器 List : | |
685 | 735 | 扩展标准库头 <list> ,提供类模板作为和 ISO C++17 std::list 类似且提供标准草案的一些其它接口。未来可能提供其它关联的 API 。 |
686 | 736 | 附加 ISO C++11 不保证的附加特性不依赖 ISO C++17 及其具体实现。 |
687 | 737 | |
688 | -@2.5.10.9 作为关联容器和无序容器实现的节点句柄 NodeHandle : | |
738 | +@2.5.10.10 作为关联容器和无序容器实现的节点句柄 NodeHandle : | |
689 | 739 | 提供关联容器和无序容器实现的相关类型。 |
690 | 740 | 当前暂时不公开 API ,但其中的 API 已被 Tree(@2.5.10.10) 和 HashTable(@2.5.10.13) 中的容器二进制依赖。 |
691 | 741 | |
692 | -@2.5.10.10 作为关联容器实现的树 Tree : | |
742 | +@2.5.10.11 作为关联容器实现的树 Tree : | |
693 | 743 | 提供一些例程用于作为关联容器实现的基础。 |
694 | 744 | 当前暂时不公开 API ,但其中的 API 已被 Map(@2.5.10.10) 和 Set(@2.5.10.11) 中的容器二进制依赖。未来可能会提供基于树实现关联容器公共 API 。 |
695 | 745 | |
696 | -@2.5.10.11 映射容器 Map : | |
746 | +@2.5.10.12 映射容器 Map : | |
697 | 747 | 扩展标准库头 <map> ,提供类模板作为和 ISO C++17 std::map 类似且支持不完整的键类型的实现。 |
698 | 748 | 附加 ISO C++11 不保证的附加特性不依赖 ISO C++17 及其具体实现。 |
699 | 749 | |
700 | -@2.5.10.12 集合容器 Set : | |
750 | +@2.5.10.13 集合容器 Set : | |
701 | 751 | 扩展标准库头 <set> ,提供类模板作为和 ISO C++17 std::set 类似且支持不完整的键类型的实现。 |
702 | 752 | 附加 ISO C++11 不保证的附加特性不依赖 ISO C++17 及其具体实现。 |
703 | 753 | 同时扩展标准库头 <map> ,提供和 std::set 类似的容器。 |
704 | 754 | |
705 | -@2.5.10.13 作为无序容器实现的散列表 HashTable : | |
755 | +@2.5.10.14 作为无序容器实现的散列表 HashTable : | |
706 | 756 | 提供一些例程用于作为无序容器实现的基础。 |
707 | 757 | 当前暂时不公开 API ,但其中的 API 已被 UnorderedMap(@2.5.10.14) 和 UnorderedSet(@2.5.10.15) 中的容器二进制依赖。 |
708 | 758 | |
709 | -@2.5.10.14 无序映射容器 UnorderedMap : | |
759 | +@2.5.10.15 无序映射容器 UnorderedMap : | |
710 | 760 | 扩展标准库头 <unordered_map> ,提供类模板作为和 ISO C++20 std::unordered_map 类似且支持不完整的键类型的实现。 |
711 | 761 | 附加 ISO C++11 不保证的附加特性不依赖 ISO C++20 及其具体实现。 |
712 | 762 | |
713 | -@2.5.10.15 无序集合容器 UnorderedSet : | |
763 | +@2.5.10.16 无序集合容器 UnorderedSet : | |
714 | 764 | 扩展标准库头 <unordered_set> ,提供类模板作为和 ISO C++20 std::unordered_set 类似且支持不完整的键类型的实现。 |
715 | 765 | 附加 ISO C++11 不保证的附加特性不依赖 ISO C++20 及其具体实现。 |
716 | 766 | |
717 | -@2.5.10.16 平坦映射容器 FlatMap : | |
767 | +@2.5.10.17 平坦映射容器 FlatMap : | |
718 | 768 | 提供 ISO C++23 标准库头 <flat_map> 的替代接口和实现。 |
719 | 769 | 不支持 <compare> 。 |
720 | 770 | 不支持 from_range_t 构造。 |
721 | 771 | |
722 | -@2.5.10.17 平坦集合容器 FlatSet : | |
772 | +@2.5.10.18 平坦集合容器 FlatSet : | |
723 | 773 | 提供 ISO C++23 标准库头 <flat_set> 的替代接口和实现。 |
724 | 774 | 不支持 <compare> 。 |
725 | 775 | 不支持 from_range_t 构造。 |
726 | 776 | |
727 | -@2.5.10.18 ISO C++ 标准流缓冲扩展 StreamBuffer : | |
777 | +@2.5.10.19 ISO C++ 标准流缓冲扩展 StreamBuffer : | |
728 | 778 | 扩展标准库头 <streambuf> 。 |
729 | 779 | |
730 | -@2.5.10.19 ISO C++ 标准输入流扩展 InputStream : | |
780 | +@2.5.10.20 ISO C++ 标准输入流扩展 InputStream : | |
731 | 781 | 扩展标准库头 <istream> 。 |
732 | 782 | |
733 | -@2.5.10.20 ISO C 标准输入/输出扩展 CStandardIO : | |
783 | +@2.5.10.21 ISO C++ 时间接口扩展 Chrono : | |
784 | +扩展标准库头 <chrono> 。 | |
785 | + | |
786 | +@2.5.10.22 ISO C 日期和时间接口扩展 CTime : | |
787 | +头文件扩展标准库头 <ctime> 。 | |
788 | + | |
789 | +@2.5.10.23 ISO C 标准输入/输出扩展 CStandardIO : | |
734 | 790 | 头文件扩展标准库头 <cstdio> ,提供 C/C++ 流操作模式参数的转换和 C 标准库输入的迭代器包装。 |
735 | 791 | |
736 | -@2.5.10.21 ISO C++ <future> 扩展 Future : | |
792 | +@2.5.10.24 ISO C++ <future> 扩展 Future : | |
737 | 793 | 扩展标准库头 <future> ,提供一些别名模板和便利接口。 |
738 | 794 | |
739 | -@2.5.10.22 伪互斥量 PseudoMutex : | |
795 | +@2.5.10.25 伪互斥量 PseudoMutex : | |
740 | 796 | 提供单线程环境下互斥量和锁接口,作为标准库 <mutex> 的替代。 |
741 | 797 | |
742 | 798 | @2.5.11 其它扩展接口: |
@@ -748,35 +804,31 @@ | ||
748 | 804 | @2.5.11.2 C++ 转换模板 Cast : |
749 | 805 | 实现各种带类型限制的转换模板。 |
750 | 806 | |
751 | -@2.5.11.3 通用容器操作 Container : | |
752 | -实现通用容器适配器模板和对容器类型及构建数组容器的操作。 | |
753 | -参数限制同 Algorithm(@2.5.10.3) 。 | |
754 | - | |
755 | -@2.5.11.4 动态泛型迭代器 AnyIterator : | |
807 | +@2.5.11.3 动态泛型迭代器 AnyIterator : | |
756 | 808 | 基于 Any(@2.5.9.20) 实现的用于保存运行时确定类型迭代器的对象。 |
757 | 809 | |
758 | -@2.5.11.5 基于类继承的混入接口 Mixin : | |
810 | +@2.5.11.4 基于类继承的混入接口 Mixin : | |
759 | 811 | 提供基本的混入接口类型。 |
760 | 812 | |
761 | -@2.5.11.6 间接和惰性求值 Thunk : | |
813 | +@2.5.11.5 间接和惰性求值 Thunk : | |
762 | 814 | 提供组合惰性求值的可调用对象。 |
763 | 815 | |
764 | -@2.5.11.7 作用域守卫 ScopeGuard | |
816 | +@2.5.11.6 作用域守卫 ScopeGuard | |
765 | 817 | 提供若干恢复状态的 RAII 包装。 |
766 | 818 | |
767 | -@2.5.11.8 有理数运算 Rational : | |
819 | +@2.5.11.7 有理数运算 Rational : | |
768 | 820 | 提供定点数模板等有理数算术类型接口。 |
769 | 821 | |
770 | -@2.5.11.9 位段数据结构和访问 BitSegment : | |
822 | +@2.5.11.8 位段数据结构和访问 BitSegment : | |
771 | 823 | 提供访问位集合的类型和操作。 |
772 | 824 | |
773 | -@2.5.11.10 并发操作 Concurrency : | |
825 | +@2.5.11.9 并发操作 Concurrency : | |
774 | 826 | 提供线程池等实用并发特性。 |
775 | 827 | |
776 | -@2.5.11.11 抽象路径模板 Path : | |
828 | +@2.5.11.10 抽象路径模板 Path : | |
777 | 829 | 提供抽象的路径模板及操作。 |
778 | 830 | |
779 | -@2.5.11.12 高速缓冲容器模板 Cache : | |
831 | +@2.5.11.11 高速缓冲容器模板 Cache : | |
780 | 832 | 提供抽象的缓冲容器模板及操作。 |
781 | 833 | |
782 | 834 | @2.6 LibDefect : |