On Wed, Jan 11, 2017 at 5:45 PM, Christof Donat
Hi,
Am 11.01.2017 16:03, schrieb Olaf van der Spek:
On Wed, Jan 11, 2017 at 10:02 AM, Christof Donat
wrote: The significantly better alternative is std::ostringstream. I think our debate showed very nicely, that all the options, we have come up with to simplify the concatenation of strings are significantly inferior in total, though we could find examples, where they slightly improve readability.
Interface is important, as is performance.. and performence of ostringstream sucks..
Well, but obviously up to now we didn't manage to come up with a solution, that has a similar simple, maybe even better interface and allows for faster implementations.
I'll try again:
Basically the Idea of that kind of interface should work as well for a high performance solution. Let's start with this syntax:
auto myString = (cat() + "Hello"s + " "s + "World! "s + 42).str();
I like fmt's syntax much more: string s = fmt::format("The answer is {}", 42); http://fmtlib.net/latest/index.html I really don't get why we should bother with the (cat(...)).str() bit.
"cat" would return an object that collects all the values by reference, and concatenates them in one go in the call to str(). Then when str() runs, the information about the string length can be calculated, or at least estimated correctly and no data needs to be copied unnecessarily. I am sure, you see the structural similarity to the usage of std::ostringstream as well. I just chose to use the operator +, because
1. we don't have stream manipulators here, so we don't want people to think, that we are talking about streams and 2. strings already can be concatenated with operator +. Therefore this is an intuitive and not very surprising interface for string concatenation.
People might just think, they can add numbers to strings as well without a "cat"-object. There is some room for confusion, but it is much less, than people thinking, strings are a kind of streams. Maybe "cat" is not the best name for this function template, it should express, that here the concatenation includes conversions.
We also need an extensible way to define these conversions, because we also will want to add e.g. complex
to a string. We also will want to define the format, because sometimes, we'll want to concat a number in decimal representation, sometimes in hexadecimal, octal, etc. I think, these conversion functions should write to a string view. e.g.: template <> // the default conversion for this type void boost::cat::convert
>(std::string_view& output, size_t max_length, const complex<...>& data); We could use parameters to cat to define conversion functions.
auto myString = (cat(hex<int>) + 42).str();
If you want that kind of formatting I'd really go for http://fmtlib.net/latest/syntax.html
I am not sure now, if that syntax is so great to define the conversion functions. We'll have to discuss.
Of course there should be an optimized default conversion function for cat-objects as well:
auto myString = (cat() + "Hello"s + " "s + "World! "s + 42 + (cat(hex<int>) + " "s + 42)).str();
Here the outer cat-object would "steal" the values from the inner cat-object and use its conversion functions directly with a view on the big result string.
I understand, that the syntax is not 100% what you try to achieve, but I still think, that conversion to string should not be directly done on a string object. This specific object to do concatenation and conversion actually is the key to gain the maximum possible performance, because it can delay the actual concatenation and conversion to a point, where all necessary information is available.
True, but then we're back again to an append / sprint style function. -- Olaf