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.
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.
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 theformatter
specializationtemplate<size_t N> struct formatter<const charT[N], charT>
. Rationale: Theformatter
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 theformatter
specializationtemplate<size_t N> struct formatter<const charT[N], charT>
. Rationale: The specialization is inconsistent with the design offormatter
, 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.