Title
format_to must not copy models of output_iterator<const charT&>
Status
new
Section
[format.functions]
Submitter
Casey Carter

Created on 2021-03-31.00:00:00 last changed 2 weeks ago

Messages

Date: 2021-04-04.13:18:04

Proposed resolution:

This wording is relative to N4885.

  1. Modify [format.functions] as indicated:

    template<class Out, class... Args>
      Out format_to(Out out, string_view fmt, const Args&... args);
    template<class Out, class... Args>
      Out format_to(Out out, wstring_view fmt, const Args&... args);
    

    -8- Effects: Equivalent to:

    using context = basic_format_context<Out, decltype(fmt)::value_type>;
    return vformat_to(std::move(out), fmt, make_format_args<context>(args...));
    
    template<class Out, class... Args>
      Out format_to(Out out, const locale& loc, string_view fmt, const Args&... args);
    template<class Out, class... Args>
      Out format_to(Out out, const locale& loc, wstring_view fmt, const Args&... args);
    

    -9- Effects: Equivalent to:

    using context = basic_format_context<Out, decltype(fmt)::value_type>;
    return vformat_to(std::move(out), loc, fmt, make_format_args<context>(args...));
    
Date: 2021-03-31.00:00:00

[format.functions] specifies the overloads of format_to as:

template<class Out, class... Args>
  Out format_to(Out out, string_view fmt, const Args&... args);
template<class Out, class... Args>
  Out format_to(Out out, wstring_view fmt, const Args&... args);

-8- Effects: Equivalent to:

using context = basic_format_context<Out, decltype(fmt)::value_type>;
return vformat_to(out, fmt, make_format_args<context>(args...));
template<class Out, class... Args>
  Out format_to(Out out, const locale& loc, string_view fmt, const Args&... args);
template<class Out, class... Args>
  Out format_to(Out out, const locale& loc, wstring_view fmt, const Args&... args);
  Out format_to(Out out, wstring_view fmt, const Args&... args);

-9- Effects: Equivalent to:

using context = basic_format_context<Out, decltype(fmt)::value_type>;
return vformat_to(out, loc, fmt, make_format_args<context>(args...));

but the overloads of vformat_to take their first argument by value (from the same subclause):

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

-10- Let charT be decltype(fmt)::value_type.

-11- Constraints: Out satisfies output_iterator<const charT&>.

-12- Preconditions: Out models output_iterator<const charT&>.

and require its type to model output_iterator<const charT&>. output_iterator<T, U> refines input_or_output_iterator<T> which refines movable<T>, but it notably does not refine copyable<T>. Consequently, the "Equivalent to" code for the format_to overloads is copying an iterator that could be move-only. I suspect it is not the intent that calls to format_to with move-only iterators be ill-formed, but that it was simply an oversight that this wording needs updating to be consistent with the change to allow move-only single-pass iterators in C++20.

History
Date User Action Args
2021-04-04 13:18:04adminsetmessages: + msg11757
2021-03-31 00:00:00admincreate