template<size_t N> struct formatter<const charT[N], charT>
Section: 28.5.6.4 [format.formatter.spec] Status: C++23 Submitter: Mark de Wever Opened: 2022-11-27 Last modified: 2023-11-22
Priority: 2
View other active issues in [format.formatter.spec].
View all other issues in [format.formatter.spec].
View all issues with C++23 status.
Discussion:
In the past I discussed with Victor and Charlie to remove
template<size_t N> struct formatter<const charT[N], charT>;
Charlie disliked that since MSVC STL already shipped it and Victor
mentioned it was useful. Instead of proposing to remove the
specialization in LWG 3701 ("Make formatter<remove_cvref_t<const charT[N]>, charT>
requirement explicit") I proposed to keep it. It's unused but it doesn't hurt.
That was until P2585R0 "Improve default container formatting". This paper makes it no longer possible to instantiate this specialization. See here for an example and a possible work-around.
The relevant wording is 28.5.1 [format.syn]:
template<class R> constexpr unspecified format_kind = unspecified; template<ranges::input_range R> requires same_as<R, remove_cvref_t<R>> constexpr range_format format_kind<R> = see below;
combined with 28.5.7.1 [format.range.fmtkind] p1:
A program that instantiates the primary template of
format_kind
is ill-formed.
The issue is that const charT[N]
does not satisfy the requirement
same_as<R, remove_cvref_t<R>>
. So it tries to instantiate the primary
template, which is ill-formed.
I see two possible solutions:
Removing the specialization
template<size_t N> struct formatter<const charT[N], charT>;
Adding a specialization
template<class charT, size_t N> constexpr range_format format_kind<const charT[N]> = range_format::disabled;
I discussed this issue privately and got no objection for solution 1, therefore I propose to take that route. Implementations can still implement solution 2 as an extension until they are ready to ship an API/ABI break.
[2022-11-30; Reflector poll]
Set priority to 2 after reflector poll.
"Rationale is not really convincing why the first option is the right one."
"The point is not that we would need to add a format_kind specialization,
it is that the specialization is inconsistent with the design of formatter
,
which is supposed to be instantiated only for cv-unqualified non-reference types."
Previous resolution [SUPERSEDED]:
This wording is relative to N4917.
Modify 28.5.6.4 [format.formatter.spec] as indicated:
-2- Let
charT
be eitherchar
orwchar_t
. Each specialization offormatter
is either enabled or disabled, as described below. A debug-enabled specialization offormatter
additionally provides a public, constexpr, non-static member functionset_debug_format()
which modifies the state of theformatter
to be as if the type of the std-format-spec parsed by the last call toparse
were?
. Each header that declares the templateformatter
provides the following enabled specializations:
(2.1) — The debug-enabled specializations […]
(2.2) — For each
charT
, the debug-enabled string type specializationstemplate<> struct formatter<charT*, charT>; template<> struct formatter<const charT*, charT>; template<size_t N> struct formatter<charT[N], charT>;template<size_t N> struct formatter<const charT[N], charT>;template<class traits, class Allocator> struct formatter<basic_string<charT, traits, Allocator>, charT>; template<class traits> struct formatter<basic_string_view<charT, traits>, charT>;(2.3) — […]
(2.4) — […]
Add a new paragraph to C.2.10 [diff.cpp20.utilities] as indicated:
Affected subclause: 28.5.6.4 [format.formatter.spec]
Change: Remove the
formatter
specializationtemplate<size_t N> struct formatter<const charT[N], charT>
.Rationale: The
formatter
specialization was not used in the Standard library. Keeping the specialization well-formed required an additionalformat_kind
specialization.Effect on original feature: Valid C++ 2020 code that instantiated the removed specialization is now ill-formed.
[2023-02-07 Tim provides updated wording]
[Issaquah 2023-02-08; LWG]
Unanimous consent to move to Immediate.
[2023-02-13 Approved at February 2023 meeting in Issaquah. Status changed: Immediate → WP.]
Proposed resolution:
This wording is relative to N4928.
Modify 28.5.6.4 [format.formatter.spec] as indicated:
-2- Let
charT
be eitherchar
orwchar_t
. Each specialization offormatter
is either enabled or disabled, as described below. A debug-enabled specialization offormatter
additionally provides a public, constexpr, non-static member functionset_debug_format()
which modifies the state of theformatter
to be as if the type of the std-format-spec parsed by the last call toparse
were?
. Each header that declares the templateformatter
provides the following enabled specializations:
(2.1) — The debug-enabled specializations […]
(2.2) — For each
charT
, the debug-enabled string type specializationstemplate<> struct formatter<charT*, charT>; template<> struct formatter<const charT*, charT>; template<size_t N> struct formatter<charT[N], charT>;template<size_t N> struct formatter<const charT[N], charT>;template<class traits, class Allocator> struct formatter<basic_string<charT, traits, Allocator>, charT>; template<class traits> struct formatter<basic_string_view<charT, traits>, charT>;(2.3) — […]
(2.4) — […]
Add a new paragraph to C.2.10 [diff.cpp20.utilities] as indicated:
Affected subclause: 28.5.6.4 [format.formatter.spec]
Change: Removed the
formatter
specializationtemplate<size_t N> struct formatter<const charT[N], charT>
.Rationale: The specialization is inconsistent with the design of
formatter
, which is intended to be instantiated only with cv-unqualified object types.Effect on original feature: Valid C++ 2020 code that instantiated the removed specialization can become ill-formed.