Closed jiri closed 8 years ago
What's wrong with fmt::print("...\n")
?
I think that println
is of limited use because you can always specify the newline explicitly as @foonathan showed. But fmt provides sufficient infrastructure to easily and efficiently build this and similar methods without making them the part of the core library. In particular println can be written in five lines of code:
template <typename... Args>
void println(fmt::CStringRef format, const Args&... args) {
fmt::print(format, args...);
std::putc('\n', stdout);
}
Sure, and you could always use stdout
explicitly, but it's the default file for convenience. One could as well argue "What's wrong with fmt::print(stdout, "...\n")
.
Having to include an explicit newline everywhere is noisy and prone to forgetting them. There's a reason why many languages include println
in their core libraries ;) Moreover, I thought that the point of a formatting library is eliminating the reason for all those non-newline terminated prints, since I could just format them into the strings, but nevertheless, you seem to be pretty set on not including it, so feel free to keep this closed.
Cheers.
The difference from fmt::print
overload taking stdout
is that the latter saves a bit of typing
fmt::print("foo");
fmt::print(stdout, "foo");
and directly corresponds to std::printf
. But you are right, it's somewhat redundant too.
It's true that println
would save exactly zero characters. What's the approach to printing a foreign string? E.g., is something like
void foo(std::string s) {
fmt::print(s);
}
considered bad form or bad api usage? println(s)
can make the intention clearer than print("{}\n", s)
or god forbid print(s + "\n")
.
is something like ... considered bad form or bad api usage?
Yes. As with printf
, it's better to write
void foo(std::string s) {
fmt::print("{}", s);
}
Otherwise s
will be parsed as a format string and will need to be escaped.
What's wrong with
fmt::print("...\n")
?
For Windows it's: fmt::print("...\r\n")
Howto to hide this difference?
I'm vote for API extension
You can use fmt::print("...\n")
on Windows as well.
The underlying streams will translate newlines, as long as they are not binary streams. stdout by default is not, so it will properly translate newlines.
Ummmm... I like fmt::println()
UPDATE:
maybe some day it will become std::println()
What's wrong with fmt::print("...\n")?
It does not flush stream like it do std::endl
Although not mandated by the C standard, stdout
is line-buffered by default on many implementations. This means, that a call to fflush
is not necessary after printf("...\n")
or puts("...")
, and thus, fmt::print("...\n")
would indeed flush the stream.
The same applies for std::cout
, which is mandated to be line-buffered, so writing a '\n'
would flush the stream no matter what.
stdout
is line buffered only if a stream refers to a terminal. As soon as you redirect it to a pipe or to a file, it will be block buffered.
Verified on Windows
It does not flush stream like it do std::endl
That's a feature. Even with hypothetical println
you wouldn't want to always flush.
Still why don't have flushing println()? It doesn't break anything, and if it is really unneeded nobody will use it (and vise versa).
That's a feature. Even with hypothetical println you wouldn't want to always flush.
fmt::print("...\n")
could be used if flush is not need.
I agree that println
should be implemented as well. Many other programming
languages offer such a method. For example C:
#include <stdio.h>
int main() {
puts("abcde");
}
C#:
using System;
class Program {
static void Main() {
Console.WriteLine("abcde");
}
}
Go:
package main
import "fmt"
func main() {
fmt.Println("abcde")
}
Rust:
fn main() {
println!("abcde");
}
Nim:
echo "abcde"
Python:
print('abcde')
I honestly was shocked this isn't the default behaviour of fmt::print()
Usually if you don't want a newline, you can be explicit about this.
stdout
is line buffered only if a stream refers to a terminal. As soon as you redirect it to a pipe or to a file, it will be block buffered. Verified on Windows
Also verified on Linux Mint. When I do this for example in a Qt application using iostream, i have to put std::endl to be sure that it outputs immediately, otherwise it will arbitrarily show up.
Yeah it's annoying to explicitly flush the buffer...
I'd also like to point out that absence of such a basic ergonomic feature in the presence of features like the literal based API is kinda funny 😄
The more common use case is println and it is so trivial it should be baked in. typing \n everywhere adds too much noise.
I would speak against an implicit newline within print
, because that's disturbing. But an extra println
function wouldn't hurt. As you said, that can be easily done, so what's the reason not to do it?
After all, it's all about ergonomics in a library @vitaut .
What's the proper way to flush the buffer in current {fmt}? std::fflush
from cstdio?
@jm4R why do you hijack this thread instead of opening a new issue/question?
I've just been banging my head off this, I have a legacy logging system that I'm converting to use fmt, and I can't find any way to insert a newline at the end of log statements automatically. The problem is that @vitaut 's five-line println above (which is what I'd tried before finding this) doesn't work where it's being compiled into a library for use by other code. The compiler creates all the function signatures used by my logging code itself, and then as soon as some other piece of code imports the library and tries to pass something to the logger with a combination of types it didn't see during compilation of the logging library, the linker barfs saying it's got an undefined symbol.
So yeah. Absent a println it seems I have a choice between requiring all users of the library to start putting their newlines in themselves, or not porting it to fmt.
I have a legacy logging system that I'm converting to use fmt, and I can't find any way to insert a newline at the end of log statements automatically.
Just write your logging functions using perfect forwarding like this:
template <typename... Args>
void logWarn(fmt::format_string<Args...>&& fmt_str, Args&&... args)
{
fmt::print(stderr, "warning: {}\n", fmt::format(
std::forward<fmt::format_string<Args...>>(fmt_str), std::forward<Args>(args)...));
}
template <typename... Args>
void logInfo(fmt::format_string<Args...>&& fmt_str, Args&&... args)
{
fmt::print("info: {}\n", fmt::format(
std::forward<fmt::format_string<Args...>>(fmt_str), std::forward<Args>(args)...));
}
C++20 automatic compile-time argument checking still works fine with these, and so does manual compile-time checking with FMT_STRING
.
I think println should be added. In any case many code-bases using this fmt library would write their own println one-liner. So why not to add it here? I've read this thread and didn't find any reasonable argument against it.
Given that this discussion has been ongoing for 6 years now and that the developers behind fmtlib have shown zero interest in listening, I'd suggest any future commenters to either use the provided workaround, or just move onto other libraries with more active development.
I suggest @vitaut locks this issue, as any attempt to further convince you on this issue just adds noise in the repository activity at this point.
I've read this thread and didn't find any reasonable argument against it.
To add a feature there should be strong arguments for it not against not adding it. And so far the arguments have been somewhat lacking and some even became invalid with compile-time checks.
@jiri, no plans to lock this issue but at least please stop adding noise yourself.
@vitaut Please refrain from mentioning me again, I don't wish to continue this discussion with you. Thank you!
I've read this thread and didn't find any reasonable argument against it.
To add a feature there should be strong arguments for it not against not adding it. And so far the arguments have been somewhat lacking and some even became invalid with compile-time checks.
I completely disagree to this approach of feature management.
Yeah, if P2093 gets adopted it would make sense to be consistent.
Seems C++23 has included the println()
.
@emailstorbala fmt also now has println
This issue is finally implemented
@emailstorbala fmt also now has
println
This issue is finally implemented
oh thank you @hellow554 ! I am using Debian/trixie
with libfmt9
(9.1.0+ds1-2). Is this available in this version? Can you kindly point me to its documentation as I am unable to find it.
oh thank you @hellow554 ! I am using
Debian/trixie
withlibfmt9
(9.1.0+ds1-2). Is this available in this version? Can you kindly point me to its documentation as I am unable to find it.
As far as I can see on git blame
, it was implemented for fmt 10.0.0, but not documented.
fmt::println
seems like a natural addition to the API. Is there a reason why it's missing?