The second version I reject regardless, because it uses an overloaded operator |.
That is the adaptor API from boost::range and is the same in ranges::v3. It's not my invention.
I must admit that I share Hans' distaste of the pipe overloads. I find them
harder to read than a sequence of function calls, and to me they are not
immediately expressive.
I agree that explicit is better than implicit.
I also strongly feel that .str() is an error, since it couples the concepts
of strings with joiners, or concatenators. Strings have allocators and
traits. I feel that a free function is more decoupled, and could even go in
a separate header file to reduce complexity.
In summary,
to_string(x) is better than x.str() is better than implicit conversion.
It is my view that this little interface change would make boost::format
more std-like and consistent. It would also make template programming more
convenient, since template expansion works much more nicely with ADL than
with member functions. The ADL free functions act as glue for objects that
lack a .str() member.
e.g:
#include
Hi,
Am 24.01.2017 11:52, schrieb Hans Dembinski:
Would you prefer str(), or implicit conversion?
Please, no implicit conversion. I don't like .str() but it is better than implicit conversion. Implicit conversion is confusing, especially in the context of templates and auto.
I didn't have good reasons, but this is in line with my gut feeling. I totally agree.
If format::hex<int> is allowed to be in any position and still affect
the whole string, that is not at all intuitive.
My idea was to allow those formatting tags only at the beginning of the parameter list. Then separator("sadf") is just another formatting tag.
What happens when you
have two conflicting formatting tags in the argument list? Which one wins?
OK, here you made a point. In a specification I'd leave the behavior undefined. In an actual implementation I'd have the later ones overwrite the previous ones, because I expect that to be easy to implement. We could also try and prevent that with meta programming, but I think, that is not worth the effort. Leaving it unspecified in the specification, still leaves us the option to do that later.
join(hex<int>, separator(" "), my_nums);
Here all the numbers are converted to their hex representation. With your approach this would look like:
join(separator(" "), my_nums | transform([](int i) -> int { return hex(i); }));
That is much more difficult to understand.
I don't see how that follows. You are free to write an overload for "join" which accepts an unary function as the first argument, which is then applied to all the values in the range. If hex<int> is an unary function, the first version makes even more sense.
I think, that composes less elegantly with boost::range or ranges::v3. Maybe we could lean towards their adaptor APIs like this:
join(separator(" "), my_nums | hex<int>()));
Still separator("...") is a bit out of the picture now. Up to mow I thought, that it is some kind of formatting information and therefore I handled it like other formatting tags. Actually I begin to like the idea of formatting functions, that return string factories. That fits very nicely with the rest of the API and makes concat(), join() and format() simpler.
A completely different approach, inspired by Python:
separator(" ").join(my_nums | hex<int>());
Then we add free functions like this:
template
}
The second version I reject regardless, because it uses an overloaded
operator |.
That is the adaptor API from boost::range and is the same in ranges::v3. It's not my invention.
Christof
_______________________________________________ Unsubscribe & other changes: http://lists.boost.org/mailman /listinfo.cgi/boost