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.

4146. §[format.formatter.spec]/3 unconditionally enables nonlocking for container adaptors

Section: 28.5.6.4 [format.formatter.spec], 23.6.13 [container.adaptors.format] Status: New Submitter: Casey Carter Opened: 2024-08-31 Last modified: 2024-09-01

Priority: Not Prioritized

View other active issues in [format.formatter.spec].

View all other issues in [format.formatter.spec].

View all issues with New status.

Discussion:

28.5.6.4 [format.formatter.spec]/3 says that the library provides a specialization of enable_nonlocking_formatter_optimization with value true corresponding to each library-provided specialization of formatter, unless otherwise specified. Although it actually states "for each type T", the intent is that partial specializations are also provided corresponding to library-provided partial specializations of formatter.

23.6.13 [container.adaptors.format]/1 says the library provides a partial specialization of formatter for each of the container adaptor templates priority_queue, queue, and stack. Together with 28.5.6.4 [format.formatter.spec]/3, that means that e.g. enable_nonlocking_formatter_optimization<stack<T>> == true. Formatting a stack of that type will enable the nonlocking optimization even if enable_nonlocking_formatter_optimization<T> == false. To avoid this, the author of T must partially specialize enable_nonlocking_formatter_optimization to false for all container adaptors when they adapt a container of T.

It is clearly not the design intent that programmers must explicitly opt out of the nonlocking optimization, so this is a defect that LWG should correct. Since P3235R3 was applied as a Defect Report to C++23, the resolution of this issue should be so applied as well.

Suggested Resolution:

LEWG was reticent to apply the optimization to general ranges — ostensibly due to the possibility of deadlock in program-defined iterator operations — but apparently unconcerned about the iterators of program-defined containers nor the fancy pointers of program-defined allocators. It seems consistent with that design to ignore the "container" part of "container adaptors" and only pay attention to the elements that are going to be formatted. (I have prototyped this resolution on MSVCSTL, albeit slightly modified since neither MSVC nor Clang like this partial specialization form.)

Proposed resolution:

This wording is relative to N4988.

  1. Modify 23.6.13 [container.adaptors.format] as indicated:

    -1- For each of queue, priority_queue, and stack, the library provides the following formatter specializations 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> {
        […]
      };
    
      template<class T, class Container, class... U>
      constexpr bool enable_nonlocking_formatter_optimization<adaptor-type<T, Container, U...>> =
        enable_nonlocking_formatter_optimization<T>;
    }