Boost logo

Boost :

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


Hi,

Am 18.01.2017 10:59, schrieb Richard Hodges:
> int main()
> {
> auto s= std::string("foo");
>
> s = join("Hello ", ", World.", " The hex for ", 58, " is ",
> std::hex, 58);
> std::cout << s << std::endl;
>
> s = join(separator(" : "), "a", "b", std::hex, 200 ,
> std::quoted("banana"));
> std::cout << s << std::endl;
>
> join(onto(s), separator(", "), "funky", "chicken");
> join(onto(s), "=====");
> std::cout << s << std::endl;
> }

I do like the idea, but not the naming. With a function name "join" I'd
expect to be able to pass an iterator range and have all its element
concatenated into a string with a defined separator like this:

auto my_number = std::vector<int>{1, 2, 3, 4, 5, 6, 7, 8, 9, 10};
std::cout << join(std::begin(my_number), std::end(my_number), ", ") <<
std::endl;

expected output:

1, 2, 3, 4, 5, 6, 7, 8, 9, 10

maybe the name cat(), or concatenate() would fit better here.

Also I am not 100% happy with is the reuse of iostream manipulators.
They already don't have a distinct range of effect in iostream library.
Another issue is, that the way, they work, is pretty complicated to be
reused in a high performance implementation.

How about an API like this:

s = concat("Hello ", ", World.", " The hex for ", 58, " is ",
concat_lib::hex(58));
s = concat(separator(" : "), "a", "b", concat_lib::hex(100),
std::quoted("banana"));

concat(onto(s), separator(", "), "funky", "chicken"); // will return a
reference to s I guess
concat(onto(s), "=====");

This would go well with what I'd expect with the function name join():

s = join(std::begin(my_number), std::end(my_number));
// -> "12345678910"
s = join(separator(", "), std::begin(my_number), std::end(my_number));
// -> "1, 2, 3, 4, 5, 6, 7, 8, 9, 10"
join(onto(s), separator(" - "), std::begin(my_number),
std::end(my_number));
// -> "1, 2, 3, 4, 5, 6, 7, 8, 9, 101 - 2 - 3 - 4 - 5 - 6 - 7 - 8 - 9 -
10"

Now, when we put it like that, there is no way, to let the functions
"steal" work from each other. If you take this e.g.:

concat(on(s), join(separator(", "), std::begin(my_number),
std::end(my_number)), " ",
               join(separator(" - "), std::begin(my_number),
std::end(my_number)));

This will first execute the two join() calls that return strings, which
are then passed to concat(). Instead join() and concat() could return
objects, that can be converted to std::string. Then concat() can make
the result of join() render its output into a common buffer.

auto s = concat(join(separator(", "), std::begin(my_number),
std::end(my_number)), " ",
                 join(separator(" - "), std::begin(my_number),
std::end(my_number))).str();

Christof


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