Hi, Am 24.01.2017 12:52, schrieb Richard Hodges:
On 24 January 2017 at 12:17, Christof Donat
wrote: Am 24.01.2017 11:29, schrieb Richard Hodges:
Imagine a function:
void foo(std::string_view s);
which we then call with:
foo(join("the answer to life, the universe and everything is: ", hex(42)));
Did you mean
foo(concat(hex<int>, "the answer to life, the universe and everything is: ", 42));
I probably meant: foo(to_string_view(concat("the answer to life, the universe and everything is: ", hex(42)))); or foo(to_string_view(join(separator(' '), "the answer to life, the universe and everything is:", hex(42))));
The idea being to avoid the construction of any un-necessary string objects. The generator already contains a buffer (or could) so it seems wasteful to me to create a string temporary simply to view its buffer.
The idea was, that not the generator holds a buffer, but the function, that actually executes it, instantiates a std::string. When that is returned, either the compiler elides that copy, or it will be moved out. So in reality the waste is very minimal, if not non existent.
The generator returned by join would stay alive until the end of the function foo, so there would be no need to construct a string, only to take a string_view of it. We could use the string_view implicit in the joiner object. This saves us an allocation and a copy.
I see. So the string would live inside the string factory as a member object, when we implicitly convert to a string_view. With C++17 std::string will have an implicit conversion operator to std::string_view. So this will be sufficient:
A string, a string-like buffer, or a reference to a string. I feel that the generator should be able to work on a supplied string reference so that it can be used to extend an existing string without reallocations or copies if required.
Yes, that is possible, when the function, that executes the generator is responsible for the buffer. Then you can have e.g. concat(...).str(); // allocate a string and return it concat(...).append_to(s); // append to an existing string; concat(...).replace(s); // write over an existing string, reusing its memory. I think, we all agree here, that implicit conversion is not the way to go. So my current proposal still is .str(), and the like. You propose free functions instead.
Yes, but I don't get why you want wide string versions for UTF-8-support. I sit about converting wide string to utf8? Like this:
std::string{concat(my_wide_string)};
Maybe to_utf8(concat(...)); would be better.
Uh, coming back to the formatting tags and my currently preferred syntax: concat(utf_8, ...).str(); If you need additional options for utf_8, it can be a function call: concat(utf_8(more, options), ...).str();
It's again explicit and could be given options to control behaviour. It also decouples the concept of UTF8 from the concept of concatenation. This adheres more to the c++ way of only paying for what you need.
The functions, that execute the string factories should, in my opinion, only care, if they have enough memory, and let the factories care about the content. Therefore I think, that the question of character encoding should be dealt with in the factories. I don't see, how the question of character encoding can be decoupled from the concept of converting arbitrary objects to strings. The converter has to have a way to encode its result. Christof