Skip to content

Commit af2c18c

Browse files
Implement range-default-formatter
The following tests are derived from libc++'s test files: - `P2286R8_text_formatting_range_map` - `P2286R8_text_formatting_range_sequence` - `P2286R8_text_formatting_range_set` - `P2286R8_text_formatting_range_string` Note that libc++'s `range_formatter` is currently buggy on the `m` option, see LLVM-90196 and LLVM-94562. The test `P2286R8_text_formatting_tuple_disambiguation` covers formatting `pair`s and `tuple`s that are also ranges.
1 parent e36ee6c commit af2c18c

File tree

15 files changed

+6577
-480
lines changed

15 files changed

+6577
-480
lines changed

stl/inc/__msvc_formatter.hpp

Lines changed: 53 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -47,6 +47,9 @@
4747
#include <cstddef>
4848
#include <cstdint>
4949
#include <type_traits>
50+
#if _HAS_CXX23
51+
#include <xutility>
52+
#endif // _HAS_CXX23
5053

5154
#pragma pack(push, _CRT_PACKING)
5255
#pragma warning(push, _STL_WARNING_LEVEL)
@@ -268,17 +271,62 @@ struct formatter<basic_string_view<_CharT, _Traits>, _CharT>
268271
};
269272

270273
#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 };
273275

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+
}();
276310

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.
278313

279314
// Per LWG-3997, `_CharT` in library-provided `formatter` specializations is
280315
// constrained to character types supported by `format`.
281316

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+
282330
template <_Format_supported_charT _CharT, class _Ty1, class _Ty2>
283331
struct formatter<pair<_Ty1, _Ty2>, _CharT>;
284332

0 commit comments

Comments
 (0)