|
47 | 47 | #include <cstddef>
|
48 | 48 | #include <cstdint>
|
49 | 49 | #include <type_traits>
|
| 50 | +#if _HAS_CXX23 |
| 51 | +#include <xutility> |
| 52 | +#endif // _HAS_CXX23 |
50 | 53 |
|
51 | 54 | #pragma pack(push, _CRT_PACKING)
|
52 | 55 | #pragma warning(push, _STL_WARNING_LEVEL)
|
@@ -268,17 +271,62 @@ struct formatter<basic_string_view<_CharT, _Traits>, _CharT>
|
268 | 271 | };
|
269 | 272 |
|
270 | 273 | #if _HAS_CXX23
|
271 |
| -_EXPORT_STD template <class, class> |
272 |
| -struct pair; |
| 274 | +_EXPORT_STD enum class range_format { disabled, map, set, sequence, string, debug_string }; |
273 | 275 |
|
274 |
| -_EXPORT_STD template <class...> |
275 |
| -class tuple; |
| 276 | +template <class _Ty> |
| 277 | +struct _Invalid_format_kind { |
| 278 | + static_assert(_Always_false<_Ty>, "A program that instantiates the primary template of format_kind is ill-formed. " |
| 279 | + "(N4981 [format.range.fmtkind]/1)"); |
| 280 | +}; |
| 281 | + |
| 282 | +_EXPORT_STD template <class _Ty> |
| 283 | +constexpr _Invalid_format_kind<_Ty> format_kind; |
| 284 | + |
| 285 | +template <class _Ty> |
| 286 | +constexpr bool _Is_two_tuple = false; |
| 287 | + |
| 288 | +template <class _Ty, class _Uty> |
| 289 | +constexpr bool _Is_two_tuple<pair<_Ty, _Uty>> = true; |
| 290 | + |
| 291 | +template <class _Ty, class _Uty> |
| 292 | +constexpr bool _Is_two_tuple<tuple<_Ty, _Uty>> = true; |
| 293 | + |
| 294 | +template <_RANGES input_range _Rng> |
| 295 | + requires same_as<_Rng, remove_cvref_t<_Rng>> |
| 296 | +constexpr range_format format_kind<_Rng> = []() consteval { |
| 297 | + using _Ref_value_t = remove_cvref_t<_RANGES range_reference_t<_Rng>>; |
| 298 | + if constexpr (same_as<_Ref_value_t, _Rng>) { |
| 299 | + return range_format::disabled; |
| 300 | + } else if constexpr (requires { typename _Rng::key_type; }) { |
| 301 | + if constexpr (requires { typename _Rng::mapped_type; } && _Is_two_tuple<_Ref_value_t>) { |
| 302 | + return range_format::map; |
| 303 | + } else { |
| 304 | + return range_format::set; |
| 305 | + } |
| 306 | + } else { |
| 307 | + return range_format::sequence; |
| 308 | + } |
| 309 | +}(); |
276 | 310 |
|
277 |
| -// Specializations for pairs and tuples are forward-declared to avoid any risk of using the disabled primary template. |
| 311 | +// Specializations for pairs, tuples and ranges are forward-declared to avoid any risk of using the disabled primary |
| 312 | +// template. |
278 | 313 |
|
279 | 314 | // Per LWG-3997, `_CharT` in library-provided `formatter` specializations is
|
280 | 315 | // constrained to character types supported by `format`.
|
281 | 316 |
|
| 317 | +template <class _Rng> |
| 318 | +concept _Formatting_enabled_range = format_kind<_Rng> != range_format::disabled; |
| 319 | + |
| 320 | +template <_RANGES input_range _Rng, _Format_supported_charT _CharT> |
| 321 | + requires _Formatting_enabled_range<_Rng> |
| 322 | +struct formatter<_Rng, _CharT>; |
| 323 | + |
| 324 | +_EXPORT_STD template <class, class> |
| 325 | +struct pair; |
| 326 | + |
| 327 | +_EXPORT_STD template <class...> |
| 328 | +class tuple; |
| 329 | + |
282 | 330 | template <_Format_supported_charT _CharT, class _Ty1, class _Ty2>
|
283 | 331 | struct formatter<pair<_Ty1, _Ty2>, _CharT>;
|
284 | 332 |
|
|
0 commit comments