4106. basic_format_args should not be default-constructible

Section: 28.5.8.3 [format.args] Status: WP Submitter: Hewill Kang Opened: 2024-05-17 Last modified: 2024-07-08

Priority: Not Prioritized

View all other issues in [format.args].

View all issues with WP status.

Discussion:

It's unclear why basic_format_args originally provided a default constructor and its actual use cases, all three major libraries declare them as default, which allows value initialization of basic_format_args at compile time.

This does not fully conform to the current wording as its signature does not have the constexpr specifier.

Additionally, the current wording only initializes the size_ member in the default constructor, which may lead to undefined behavior when copying basic_format_args as uninitialized data_ member is copied. There is also an implementation divergence (demo):

#include <format>
constexpr std::format_args fmt_args; // only well-formed in MSVC-STL

One option is to add default member initializers for all members and default the default constructor to best match the status quo, which guarantees that basic_format_args is constexpr-able.

However, given that basic_format_args has different implementation details in the three libraries, its actual members may not be size_ and data_. It is unnecessary to ensure that all the internal members are initialized when default-constructed basic_format_args, indicating that not providing one is reasonable.

The proposed solution is to prefer the more aggressive one.

[2024-05-19; Daniel comments]

The here suggested proposal to remove the default constructor implicitly depends on the decision of LWG 4061 to remove basic_format_context's default constructor, since its usage would require that the exposition-only member args_ of type basic_format_args<basic_format_context> can be default-constructed as well.

[2024-06-24; Reflector poll]

Set status to Tentatively Ready after eight votes in favour during reflector poll.

[St. Louis 2024-06-29; Status changed: Voting → WP.]

Proposed resolution:

This wording is relative to N4981.

  1. Modify 28.5.8.3 [format.args] as indicated:

    namespace std {
      template<class Context>
      class basic_format_args {
        size_t size_;                               // exposition only
        const basic_format_arg<Context>* data_;     // exposition only
    
      public:
        basic_format_args() noexcept;
    
        template<class... Args>
          basic_format_args(const format-arg-store<Context, Args...>& store) noexcept;
    
        basic_format_arg<Context> get(size_t i) const noexcept;
      };
      […]
    }
    
    […]
    basic_format_args() noexcept;
    

    -2- Effects Initializes size_ with 0.