3336. How does std::vformat handle exception thrown by formatters?

Section: 28.5.5 [format.functions] Status: Resolved Submitter: Tam S. B. Opened: 2019-11-11 Last modified: 2020-09-06

Priority: 2

View all other issues in [format.functions].

View all issues with Resolved status.

Discussion:

The specification for std::vformat in 28.5.5 [format.functions]/7 says

Throws: format_error if fmt is not a format string.

It seems unclear whether vformat throws when an exception is thrown by the formatter, e.g. when the format string is valid, but the corresponding argument cannot be formatted with the given format string.

For example, the "c" format specifier is specified to throw format_error if the corresponding argument is not in the range of representable values for charT (Table 60 [tab:format.type.int]). It seems unclear whether vformat propagates this exception.

It also appears unclear whether vformat may throw other types of exception (e.g. bad_alloc) when the formatter or the constructor of std::string result throws.

[2019-11-20 Issue Prioritization]

Priority to 2 after reflector discussion.

[2019-11-20; Victor Zverovich provides initial wording]

Previous resolution [SUPERSEDED]:

This wording is relative to N4835.

[Drafting Note: LWG 3340 has considerable wording overlap with this issue. If LWG 3336 is applied at the same meeting or later than LWG 3340, please refer to Option A in LWG 3340 as a guideline how to apply the merge.]

  1. Before 28.5.5 [format.functions] insert a new sub-clause as indicated:

    20.20.? Error reporting [format.err.report]

    -?- Formatting functions throw exceptions to report formatting and other errors. They throw format_error if an argument fmt is passed that is not a format string and propagate exceptions thrown by formatter specializations and iterator operations. Failure to allocate storage is reported by throwing an exception as described in 16.4.6.13 [res.on.exception.handling].

  2. Modify 28.5.5 [format.functions] as indicated:

    string vformat(string_view fmt, format_args args);
    wstring vformat(wstring_view fmt, wformat_args args);
    string vformat(const locale& loc, string_view fmt, format_args args);
    wstring vformat(const locale& loc, wstring_view fmt, wformat_args args);
    

    -6- […]

    -7- Throws: format_error if fmt is not a format stringAs specified in 28.5.3 [format.err.report].

    […]
    template<class Out>
      Out vformat_to(Out out, string_view fmt, format_args_t<Out, char> args);
    template<class Out>
      Out vformat_to(Out out, wstring_view fmt, format_args_t<Out, wchar_t> args);
    template<class Out>
      Out vformat_to(Out out, const locale& loc, string_view fmt,
                     format_args_t<Out, char> args);
    template<class Out>
      Out vformat_to(Out out, const locale& loc, wstring_view fmt,
                     format_args_t<Out, wchar_t> args);
    

    […]

    -15- Throws: format_error if fmt is not a format stringAs specified in 28.5.3 [format.err.report].

    […]
    template<class Out, class... Args>
      format_to_n_result<Out> format_to_n(Out out, iter_difference_t<Out> n,
                                          string_view fmt, const Args&... args);
    template<class Out, class... Args>
      format_to_n_result<Out> format_to_n(Out out, iter_difference_t<Out> n,
                                          wstring_view fmt, const Args&... args);
    template<class Out, class... Args>
      format_to_n_result<Out> format_to_n(Out out, iter_difference_t<Out> n,
                                          const locale& loc, string_view fmt,
                                          const Args&... args);
    template<class Out, class... Args>
      format_to_n_result<Out> format_to_n(Out out, iter_difference_t<Out> n,
                                          const locale& loc, wstring_view fmt,
                                          const Args&... args);
    

    […]

    -21- Throws: format_error if fmt is not a format stringAs specified in 28.5.3 [format.err.report].

    […]
    template<class... Args>
      size_t formatted_size(string_view fmt, const Args&... args);
    template<class... Args>
      size_t formatted_size(wstring_view fmt, const Args&... args);
    template<class... Args>
      size_t formatted_size(const locale& loc, string_view fmt, const Args&... args);
    template<class... Args>
      size_t formatted_size(const locale& loc, wstring_view fmt, const Args&... args);
    

    […]

    -25- Throws: format_error if fmt is not a format stringAs specified in 28.5.3 [format.err.report].

[2020-02-12, Prague; LWG discussion]

Resolved by LWG 3340.

Proposed resolution:

Resolved by LWG 3340.