4

Why is it fmt::format_to(OutputIt, ...) and not fmt::print(OutputIt, ...)??


I'm currently familiarizing myself with {fmt}, a / the modern C++ formatting library.

While browsing the API, I found the naming a bit disjoint, but given my little-to-no experience with the library (and my interest in API design), I would like to get behind these naming choices: (fmt core API reference)

  • There's fmt::format(...) -> std::string which makes sense, it returns a formatted string.
  • Then we have void fmt::print([stream, ] ...) which also makes sense naming wise (certainly given the printf legacy).
  • But then we have fmt::format_to(OutputIt, ...) -> OutputIt which resembles, apart from the return type, what print does with streams.

Now obviously, one can bike shed names all day, but here the question is not on why we have format vs. print (which is quite explainable to me), but why a function that clearly(?) behaves like the write-to-stream-kind has been bundled with the format_... naming style.

So, as the question title already asks, is there a technical difference in how fmt::print(stream, ...) behaves when formatting to a streams vs. how fmt::format_to(OutputIt, ...) behaves when formatting to an output iterator?

Or was/is this purely a style choice? Also, given that the GitHube repo explicitly lists the tag here, I was hoping that we could get a authoritative answer on this from the original API authors.

Martin Ba
  • 37,187
  • 33
  • 183
  • 337
  • Names are hard. :) Interested to see where this goes. – Retired Ninja Jun 30 '21 at 19:30
  • 4
    Hard? Naming is a ing battlefield. Complete with mines, barbed wire, artillery, and trenches. – user4581301 Jun 30 '21 at 19:31
  • 2
    @RetiredNinja - Personally I think we need a naming-is-hard tag, but I feel I'm in the minority on this one :-D – Martin Ba Jun 30 '21 at 19:32
  • Do not know if that is relevant to your question, but the `fmt` library made it to C++ standard and is now [part of C++20](https://en.cppreference.com/w/cpp/utility/format). However that process dropped `print` entirely. And it looks like it in fact never was part of the proposal, even the [first draft](http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2017/p0645r0.html). – spectras Jun 30 '21 at 19:57
  • Note that `print` only takes in C `FILE` stream, whereas `format_to` takes in any output iterators, includes containers' and C++ streams'. – Ranoiaetep Jun 30 '21 at 20:17
  • 1
    @Ranoiaetep `print` takes a `std::ostream&` if you `#include `. AFAIK, `format_to` can't directly write to a `std::ostream&`. – Justin Jun 30 '21 at 21:16
  • @user4581301 - I always feel more like Naming is rather like a swampy jungle. You wander in, thinking yeah, maybe one way is a little easier than the other, but maybe we could take that shortcut (on which your team obv. disagrees) and in the end you spent hours upon hours and feel lucky to have come out at all. ;-) – Martin Ba Jul 03 '21 at 11:35

1 Answers1

9

While it would be possible to name format_to print, the former is closer conceptually to format than to print. format_to is a generalization of format that writes output via an output iterator instead of std::string. Therefore the naming reflects that.

print without a stream argument on the other hand writes to stdout and print with an argument generalizes that to an arbitrary stream. Writing to a stream is fundamentally different from writing to an output iterator because it involves additional buffering, synchronization, etc. Other languages normally use "print" for this sort of functionality so this convention is followed in {fmt}.

This becomes blurry because you can have an output iterator that writes to a stream but even there the current naming reflects what high-level APIs are being used.

In other words format_to is basically a fancy STL algorithm (there is even format_to_n similarly to copy/copy_n) while print is a formatted output function.

vitaut
  • 49,672
  • 25
  • 199
  • 336