Hi, Am 13.01.2017 17:29, schrieb Peter Dimov:
Christof Donat wrote:
Am 12.01.2017 20:05, schrieb Olaf van der Spek:
I like fmt's syntax much more:
string s = fmt::format("The answer is {}", 42);
fmtlib looks pretty cool. In fact it's basically a superset of my private library. Some of the design decisions aren't the same but the overall style is very similar.
Format will have to parse the format string at runtime and then chose dynamically the function to stringify the number.
It does, of course, parse the format string, but I'm not sure what you mean by "choose function dynamically." The above basically does something like
os << "The answer is "; os << 42; return os.str();
using one virtual call for the os << 42 part.
A call to a virtual function is a dynamic choice of the function to call. A non virtual call can be inlined. Even if it is not, it is simply an absolute jump, while a virtual call is at least loading the vtable pointer and loading the pointer to the function from said vtable, before you can jump to the function. But that is not the worst part of virtual function calls. With non virtual calls, the branch prediction will always be correct, the upcoming instructions will already be loaded and fed into the pipeline, and the code runs almost as fast as the inlined version (ignoring parameter passing here, which is where inlining really pays of). Virtual function calls give the branch prediction only a statistical chance to chose correctly. When it fails, the instruction cache has to be filled with instructions from the correct branch, while the prefetched instructions, that already partially executed in the pipeline, have to be rolled back. Depending on your hardware, that might cost up to several dozens of clock cycles, in case of a cache miss. We were talking about performance here. Therefore I tried to come up with a syntax, that can be implemented without virtual function calls as much as possible and avoids parsing format strings. Also that syntax should allow for creating the result in one go, in order to avoid unnecessary reallocations. Keeping that in mind, I think, my proposal is not the worst possible, though, of course, someone might come up with a better one. Libraries like boost::format have their strengths, when simply concatenating information does not fit the needs. E.g. for internationalized text output. I like boost::format a lot, but speed actually is not its focus. auto translate(const std::string& key) -> std::string; // ... // will translate to e.g. "%2% Bytes werden von der Datei '%1%' belegt." std::cerr << boost::format(translate("file '%1%' contains %2% bytes"s)) % filename % filesize << std::endl; On the other hand e.g. for writing a set of values as CSV, my proposed interface will produce faster code: for(const auto& line : all_lines) out << (cat() + line<1> + ',' + line<2> + ',' + line<3> + ',' + line<4> + ',' + line<5> + '\n').str(); Christof