On Tue, 8 Jul 2025 at 09:23, Tomasz Kamiński <tkami...@redhat.com> wrote: > > 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?
OK, thanks > 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. I agree it's not very important to backport, but it also seems simple and safe to do so. > 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 >