[PATCH] libstdc++: Do not expose set_brackets/set_separator for formatter with format_kind other than sequence [PR119861]
Tomasz Kamiński
tkaminsk@redhat.com
Tue Jul 8 08:17:40 GMT 2025
The standard defines separate specializations of range-default-formatter, out
of which only one for range_format::sequence provide the set_brackets and
set_separator methods. We implemented it as one specialization and exposed
this method for range_format other than string or debug_string, i.e. when
range_formatter was used as underlying formatter.
PR libstdc++/119861
libstdc++-v3/ChangeLog:
* include/std/format (formatter<_Rg, _CharT>::set_separator)
(formatter<_Rg, _CharT>::set_brackets): Constrain with
(format_kind<_Rg> == range_format::sequence).
* testsuite/std/format/ranges/pr119861_neg.cc: New test.
---
Testing on x86_64-linux locally. Format test passed.
OK for trunk?
I do not think this it is necessary to backport this to 15,
as we were providing functions in more cases that needed. Let me know
what you think.
libstdc++-v3/include/std/format | 4 +-
.../std/format/ranges/pr119861_neg.cc | 52 +++++++++++++++++++
2 files changed, 54 insertions(+), 2 deletions(-)
create mode 100644 libstdc++-v3/testsuite/std/format/ranges/pr119861_neg.cc
diff --git a/libstdc++-v3/include/std/format b/libstdc++-v3/include/std/format
index 5749aa1995a..d584b81c78a 100644
--- a/libstdc++-v3/include/std/format
+++ b/libstdc++-v3/include/std/format
@@ -6030,13 +6030,13 @@ namespace __format
constexpr void
set_separator(basic_string_view<_CharT> __sep) noexcept
- requires (!_S_range_format_is_string)
+ requires (format_kind<_Rg> == range_format::sequence)
{ _M_under.set_separator(__sep); }
constexpr void
set_brackets(basic_string_view<_CharT> __open,
basic_string_view<_CharT> __close) noexcept
- requires (!_S_range_format_is_string)
+ requires (format_kind<_Rg> == range_format::sequence)
{ _M_under.set_brackets(__open, __close); }
// We deviate from standard, that declares this as template accepting
diff --git a/libstdc++-v3/testsuite/std/format/ranges/pr119861_neg.cc b/libstdc++-v3/testsuite/std/format/ranges/pr119861_neg.cc
new file mode 100644
index 00000000000..9a6ed16393e
--- /dev/null
+++ b/libstdc++-v3/testsuite/std/format/ranges/pr119861_neg.cc
@@ -0,0 +1,52 @@
+// { dg-do compile { target c++23 } }
+
+#include <format>
+#include <vector>
+
+// only format_kind::sequence provides set_brackets and set_separator methods
+
+template<std::range_format fk, typename T>
+struct MyCont : std::vector<T>
+{
+ using std::vector<T>::vector;
+};
+
+template<std::range_format fk, typename T>
+constexpr std::range_format std::format_kind<MyCont<fk, T>> = fk;
+
+void test_sequence()
+{
+ std::formatter<MyCont<std::range_format::sequence, int>, char> fmtter;
+ fmtter.set_brackets("{", "}");
+ fmtter.set_separator(",");
+}
+
+void test_map()
+{
+ std::formatter<MyCont<std::range_format::map, std::pair<int, int>>, char> fmtter;
+ fmtter.set_brackets("{", "}"); // { dg-error "here" }
+ fmtter.set_separator(","); // { dg-error "here" }
+}
+
+void test_set()
+{
+ std::formatter<MyCont<std::range_format::set, int>, char> fmtter;
+ fmtter.set_brackets("{", "}"); // { dg-error "here" }
+ fmtter.set_separator(","); // { dg-error "here" }
+}
+
+void test_string()
+{
+ std::formatter<MyCont<std::range_format::string, char>, char> fmtter;
+ fmtter.set_brackets("{", "}"); // { dg-error "here" }
+ fmtter.set_separator(","); // { dg-error "here" }
+}
+
+void test_debug_string()
+{
+ std::formatter<MyCont<std::range_format::debug_string, char>, char> fmtter;
+ fmtter.set_brackets("{", "}"); // { dg-error "here" }
+ fmtter.set_separator(","); // { dg-error "here" }
+}
+
+// { dg-error "no matching function for call to 'std::formatter<" "" { target *-*-* } 0 }
--
2.49.0
More information about the Libstdc++
mailing list