This page is a snapshot from the LWG issues list, see the Library Active Issues List for more information and the meaning of New status.

4586. Partial specialization of std::format_kind for std::optional is not marked hosted

Section: 16.3.3.7 [freestanding.item], 22.5.2 [optional.syn], 28.5.1 [format.syn] Status: New Submitter: Jiang An Opened: 2026-05-29 Last modified: 2026-05-29

Priority: Not Prioritized

View all other issues in [freestanding.item].

View all issues with New status.

Discussion:

Currently, <optional> is a mostly freestanding header and provides a partial specialization of std::format_kind which isn't mark // hosted in the synopsis (22.5.2 [optional.syn]). The current rules in 16.3.3.7 [freestanding.item] p4 seemingly requires the partial specialization to be a freestanding item, while nothing seems to requires the primary template (provided by <format>) to be freestanding.

The status quo looks quite weird. Perhaps we should make the freestanding status same for the primary template and the partial specialization.

Proposed resolution:

This wording is relative to N5046.

[Drafting Note: Three options are prepared, depicted below by Option A, Option B, and Option C, respectively, where option C is mutually exclusive with option A and B.

Note that libstdc++ effectively implemented option A recently (in commit 23b9ac257cf508bc4fa479c82fcfc768c4abcd79).]

Option A: Just marking the partial specialization hosted

  1. Modify 22.5.2 [optional.syn], header <optional> synopsis, as indicated:

    […]
    template<class T>
      constexpr bool ranges::enable_view<optional<T>> = true;
    template<class T>
      constexpr auto format_kind<optional<T>> = range_format::disabled; // hosted
    template<class T>
      constexpr bool ranges::enable_borrowed_range<optional<T&>> = true;
    […]
    

Option B: Adding a general rule that infers hosted-ness of specializations

  1. Modify 16.3.3.7 [freestanding.item] as indicated:

    -4- A declaration in a synopsis is a freestanding item if […]

    -5- An entity or deduction guide is a freestanding item if its introducing declaration is not followed by a comment that includes hosted, and is: […]

    -6- A macro is a freestanding item if it is defined in a header synopsis and […]

    -?- A partial or full template specialization is not a freestanding item if its primary template is not a freestanding item.

Option C: Making range_format and format_kind freestanding

  1. Modify Table 27 [tab:headers.cpp.fs] as indicated:

    Table 27: C++ headers for freestanding implementations [tab:headers.cpp.fs]
    Subclause Header
    […]
    28.2 [charconv] Primitive numeric conversions <charconv>
    28.5 [format] Formatting <format>
    29.5 [rand] Random number generation <random>
    […]
  2. Modify 28.5.1 [format.syn], header <format> synopsis, as indicated:

    […]
    // 28.5.7 [format.range], formatting of ranges
    // 28.5.7.1 [format.range.fmtkind], variable template format_kind
    enum class range_format {
      disabled,
      map,
      set,
      sequence,
      string,
      debug_string
    };
    
    template<class R>
      constexpr unspecified format_kind = unspecified;         // freestanding
    
    template<ranges::input_range R>
      requires same_as<R, remove_cvref_t<R>>
      constexpr range_format format_kind<R> = see below;       // freestanding
    […]