This page is a snapshot from the LWG issues list, see the Library Active Issues List for more information and the meaning of C++23 status.
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(i) ("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_kindis 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
charTbe eithercharorwchar_t. Each specialization offormatteris either enabled or disabled, as described below. A debug-enabled specialization offormatteradditionally provides a public, constexpr, non-static member functionset_debug_format()which modifies the state of theformatterto be as if the type of the std-format-spec parsed by the last call toparsewere?. Each header that declares the templateformatterprovides 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 theformatterspecializationtemplate<size_t N> struct formatter<const charT[N], charT>. Rationale: Theformatterspecialization was not used in the Standard library. Keeping the specialization well-formed required an additionalformat_kindspecialization. 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
charTbe eithercharorwchar_t. Each specialization offormatteris either enabled or disabled, as described below. A debug-enabled specialization offormatteradditionally provides a public, constexpr, non-static member functionset_debug_format()which modifies the state of theformatterto be as if the type of the std-format-spec parsed by the last call toparsewere?. Each header that declares the templateformatterprovides 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 theformatterspecializationtemplate<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.