5 ms·
> What do you use instead [of std::iostream]? This is what I want to know. Having come from C to C++, iostreams were a big improvement over the "strings" and p
by npsimons 3y ago
> What do you use instead [of std::iostream]?
This is what I want to know. Having come from C to C++, iostreams were a big improvement over the "strings" and print functions of C. I even extended a base iostream class to have a "teebuf" logger, that could output to multiple streams and had the standard logging levels.
It's been a while since I last had mastery of C++, but I'd like to hear what is as portable and better than iostreams.
- usefulcat 3y ago> I'd like to hear what is as portable and better than iostreams Have a look at fmtlib. The interface is more like printf, but type safe and format strings are parsed at compile time. I believe it’s what std::format is based on, which could also be an option for you depending on how recent your compiler/language version is.
- npsimons 3y ago> The interface is more like printf See, I don't believe that's an improvement. Having used printf in C, I was relieved to be able to "redirect" whatever to a stream, and not care about whether it should be "%d" or "%02f" or even if it was a struct/class. On top of this, treating files as streams, strings as streams, or even extending streams to make a tee-stream[0] all seem clunkier to me with a printf like system. Maybe fmt fixes these problems, I don't know. But I feel a lot of people don't like iostreams because they have some form of Stockholm syndrome with printf. [0] - https://wordaligned.org/articles/cpp-streambufs#tee-streams https://wordaligned.org/articles/cpp-streambufs#tee-streams
- dietrichepp 3y ago> Maybe fmt fixes these problems, I don't know. Yeah, it looks like you did a lot of guesswork in that comment, and a lot of those guesses were inaccurate. Not really trying to be hostile here, but you did acknowledge that you were unfamiliar with std::format. The part that fmtlib / std::format has, which is printf-like, is the idea of having a format string and arguments, rather than having a bunch of separate, piecemeal strings. // Old printf code, works ok for most people std::printf("failed to clone %s from %s", target, src); // <iostream> std::cout << "failed to clone " << target << " from " << src; // New std::format / fmtlib std::print("failed to clone {} from {}", target, src); You can see that you don't need to remember what kind of format specifier you need. This is C++, and that kind of problem is solved with overloading. The std::print interface can work equally well with FILE or std::ofstream, or whatever you want. This is C++, and so you can just use a templated output iterator—or one of the overloads that creates one automatically. There are a lot of problems with <iostream>. I think it’s telling that lots of languages have copied printf, but nobody (or almost nobody) thought <iostream> was good enough to copy. There are just too many serious design flaws with <iostream>. It would be one thing if <iostream> were just annoying to use, but it poses problems for localization, thread-safety, accidental misuse through its statefulness, and its operator overloading syntax is bad.
- tialaramex 3y ago> It would be one thing if <iostream> were just annoying to use, but it poses problems for localization, thread-safety, accidental misuse through its statefulness, and its operator overloading syntax is bad. It's Bjarne (Stroustrup)'s pet feature. You'll notice that many expert practitioners of C++ write std::println("Hello, world"); or similar for a canonical C++ 23 Hello World, but Bjarne pointedly still writes it with std::cout and the iostream operator overloads. Now that Bjarne is back at Columbia teaching, there's a risk he'll infect impressionable young people with this nonsense, COMSW4995 was not an intro class and I suspect Bjarne's jetsetting makes it impractical to teach such a class, so this risk is small but not zero.
- 95014_refugee 3y agoConsidering the origins of "stockholm syndrome" this may not be exactly the message you intended. However, printf and its ilk get it right; presentation is a property of the context in which the entity is to be presented, not of the entity itself. You can kvetch about the markup syntax, or the type safety issues the C implementation has, but the architecture is fundamentally correct.
- usefulcat 3y agofmtlib knows the types of all the arguments, and those types are checked against the format string at compile time. So type safety ("%d" vs "%s" etc) is not really an issue. FWIW, I have waaaay more experience with iostreams than printf. I once wrote a replacement for most parts of std::ostream purely because I had a logging system that was loosely based on log4cxx (which is based on iostreams) and I needed much faster formatting. Right now I'm in the process of switching to a different logging system that uses fmtlib. I can say that I really, really do not miss the extreme verbosity of iostreams at all. The statefulness I could take or leave, although on balance I'd say it's usually more of a negative. Thankfully I don't have to give up type safety or extensibility. As for treating files/strings/whatever as streams--my impression of fmtlib is that it's concerned primarily with formatting, which frankly I'm fine with. It can write to an in-memory buffer or to a FILE* or to a std::ostream, which covers pretty much all of my needs. Given the performance of iostreams (lots of virtual method calls) I never really saw the point of using it as a more generalized 'streaming' interface, even knowing that it's possible.
- dietrichepp 3y agoStrings in C++ are nice, especially now that we have std::string_view, but <iostream> is one of the worst pieces of the C++ standard library. - <iostream> makes localization more difficult, compared to printf (localizing <iostream> code is beyond awful) - <iostream> makes thread safety more difficult, compared to printf (it is safe to printf/fprintf from multiple threads, simultaneously, without any extra work) - The <iostream> operator overloading syntax is bad (my sense is that the operator overloading abuse in <iostream> was a contributing factor for why Java doesn't allow operator overloading) - Streams in <iostream> are stateful, and it's easy to accidentally leave them in the wrong state (radix, padding, field width, etc) - Performance of <iostream>, out of the box, is mediocre (to get decent performance, you need to change some defaults) The main advantage of <iostream> was that it provided type safety, but IMO that advantage has long since been irrelevant. You get type safety with std::printf, with most compilers, assuming you enable -Wformat on GCC or similar options in other compilers. The only remaining advantage of <iostream> is that you can overload operator<<. I don't think that's much of an advantage, especially weighed against the numerous disadvantages. Using std::printf is better and more portable. Libfmt is also better and more portable, and it is now part of the standard library as std::format. https://www.moria.us/articles/iostream-is-hopelessly-broken/ https://www.moria.us/articles/iostream-is-hopelessly-broken/
- therein 3y agolibfmt is definitely recommended. About 6-7 years ago back when my employer was running code compiled with gcc-4.4.7 and running it on Linux 2.6.32 boxes even though it was pretty old even back then, it took me a lot of convincing the company to give libfmt a try. It was such a boost to developer happiness. People were literally overjoyed, writing to me on Slack how much of a pleasure string formatting has become.
- offices 3y ago>The <iostream> operator overloading syntax is bad In an obnoxious way. The first code someone will see of a new language is often 'hello world'. In C++, 'hello world' is an advertisement for the fact that operator overloading exists.