Created on 2023-02-10.00:00:00 last changed 13 months ago
Proposed resolution:
This wording is relative to n4928.
Modify [container.adaptors.format] as indicated:
-1- For each of queue, priority_queue, and stack, the library provides the following formatter specialization where adaptor-type is the name of the template:
[…]namespace std { template<class charT, class T, formattable<charT> Container, class... U> struct formatter<adaptor-type<T, Container, U...>, charT> { private: using maybe-const-container = // exposition only fmt-maybe-const<Container, charT>; using maybe-const-adaptor = // exposition onlyfmt-maybe-const<is_const_v<maybe-const-container>, adaptor-type<T, Container, U...>, charT>; // see [ranges.syn] formatter<ranges::ref_view<maybe-const-container>Container, charT> underlying_; // exposition only public: template<class ParseContext> constexpr typename ParseContext::iterator parse(ParseContext& ctx); template<class FormatContext> typename FormatContext::iterator format(maybe-const-adaptor& r, FormatContext& ctx) const; }; }template<class FormatContext> typename FormatContext::iterator format(maybe-const-adaptor& r, FormatContext& ctx) const;-3- Effects: Equivalent to: return underlying_.format(r.c, ctx);
[ 2023-02-13 Approved at February 2023 meeting in Issaquah. Status changed: Immediate → WP. ]
[ Issaquah 2023-02-10; LWG issue processing ]
Move to Immediate for C++23
[ 2023-02-10 Tim provides updated wording ]
The container elements may not be const-formattable so we cannot use the const formatter unconditionally. Also the current wording is broken because an adaptor is not range and we cannot use fmt-maybe-const on the adaptor — only the underlying container.
According to [container.adaptors.format] container adapters such as std::stack are formatted by forwarding to the underlying container:
template<class FormatContext> typename FormatContext::iterator format(maybe-const-adaptor& r, FormatContext& ctx) const;Effects: Equivalent to: return underlying_.format(r.c, ctx);
This gives expected results for std::stack<T> and most types of underlying container:
auto s = std::format("{}", std::stack(std::deque{'a', 'b', 'c'})); // s == "['a', 'b', 'c']"
However, when the underlying container is std::string the output is:
auto s = std::format("{}", std::stack{std::string{"abc"}}); // s == "abc"
This is clearly incorrect because std::stack itself is not a string (it is only backed by a string) and inconsistent with formatting of ranges where non-string range types are formatted as comma-separated values delimited by '[' and ']'. The correct output in this case would be ['a', 'b', 'c'].
Here is an illustration of this issue on godbolt using {fmt} and an implementation of the formatter for container adapters based on the one from the standard: https://godbolt.org/z/P1nrM1986. A simple fix is to wrap the underlying container in std::views::all(_t) (https://godbolt.org/z/8MT1be838).This wording is relative to n4928.
Modify [container.adaptors.format] as indicated:
-1- For each of queue, priority_queue, and stack, the library provides the following formatter specialization where adaptor-type is the name of the template:
[…]namespace std { template<class charT, class T, formattable<charT> Container, class... U> struct formatter<adaptor-type<T, Container, U...>, charT> { private: using maybe-const-adaptor = // exposition only fmt-maybe-const<adaptor-type<T, Container, U...>, charT>; formatter<views::all_t<const Container&>, charT> underlying_; // exposition only public: template<class ParseContext> constexpr typename ParseContext::iterator parse(ParseContext& ctx); template<class FormatContext> typename FormatContext::iterator format(maybe-const-adaptor& r, FormatContext& ctx) const; }; }template<class FormatContext> typename FormatContext::iterator format(maybe-const-adaptor& r, FormatContext& ctx) const;-3- Effects: Equivalent to: return underlying_.format(views::all(r.c), ctx);
History | |||
---|---|---|---|
Date | User | Action | Args |
2023-11-22 15:47:43 | admin | set | status: wp -> c++23 |
2023-02-13 11:31:32 | admin | set | messages: + msg13406 |
2023-02-13 11:31:32 | admin | set | status: immediate -> wp |
2023-02-10 21:41:20 | admin | set | messages: + msg13345 |
2023-02-10 21:41:20 | admin | set | status: new -> immediate |
2023-02-10 18:49:11 | admin | set | messages: + msg13342 |
2023-02-10 17:06:30 | admin | set | messages: + msg13336 |
2023-02-10 00:00:00 | admin | create |