Search code examples
c++language-lawyerc++23fmtstdformat

What happens if arguments alias the output buffer in std::format_to?


Consider the following example:

#include <format>
#include <print>

int main() {
    int x = 12345;
    // note: this is "awoo" followed by 28 zeros ([dcl.init.string] p3)
    char buffer[32] = "awoo";
    std::format_to(buffer, "{}{}", x, buffer);
    std::println("{}", buffer);
}

This code is expected to output 12345awoo because we are formatting {}{} with arguments 12345 and "awoo".

However, the actual output is 1234512345. The reason for this is obvious: Formating 12345 would write to the buffer, and so by the time that buffer (the second argument) is being handled by std::format_to, it no longer contains "awoo".

This begs the question: What is the expected result according to the C++ standard? https://eel.is/c++draft/format.functions#lib:vformat_to does not specify as a precondition that aliasing between the arguments and the output buffer isn't permitted, so I don't believe that this case is undefined behavior.


Solution

  • It's unspecified, both 1234512345 and 12345awoo are conforming results.

    The functions defined in [format.functions] use specializations of the class template formatter to format individual arguments.

    [format.formatter.spec#1]

    Thus the formatting of each argument happens within a separate function call to the others. There isn't any requirement on the order of these calls, so the side-effects are indeterminately sequenced with each other.