I agree re naming. concat() or concatenate() seems a better fit. I also share your unease re formatting. I have of course shoehorned the ostream formatters in here without thinking it through deeply (there is also the issue of the separator getting formatted, so any sequence of formatters must be executed *after* the separator has been applied, and formatters really ought to restore previous state. I think it's reasonable to develop a series of lightweight function object factories that provide trivial formatting objects in the same way that std::quoted does for std::ostream. In that case, it is perfectly reasonable to do away with the entire atrocious ostream performance bottleneck altogether (perhaps there are questions though, about formatting options and locales?). Totally agree with returning a string factory. That makes perfect sense. onto(x) could return the correct kind of wrapper, depending on the argument type of x. So it could cope with x being for example, std::string&, std::string const&, std::string&& or std::ostream&. As an observation, expressing the join as an iterator pair lends itself to being implemented in terms of std::copy(first, last, formatting_iterator<...>). I think this is good for containers, but for a series of disjoint types, or for joining words (as opposed to letters), you'd still need some templatery. boost::range springs to mind as a reasonable helper for expressing to concat (or join) that you want to treat each element of a container. On 18 January 2017 at 16:11, Christof Donat <cd@okunah.de> wrote:
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
_______________________________________________ Unsubscribe & other changes: http://lists.boost.org/mailman /listinfo.cgi/boost