Boost logo

Boost :

Subject: Re: [boost] Variadic append for std::string
From: Christof Donat (cd_at_[hidden])
Date: 2017-01-11 11:45:44


Hi,

Am 11.01.2017 16:03, schrieb Olaf van der Spek:
> On Wed, Jan 11, 2017 at 10:02 AM, Christof Donat <cd_at_[hidden]> 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();

"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<myBigRelativeType, myBigRelativeType>
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<complex<...>>(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();

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.

Christof


Boost list run by bdawes at acm.org, gregod at cs.rpi.edu, cpdaniel at pacbell.net, john at johnmaddock.co.uk